diff --git a/IRaCIS.Core.API/Controllers/ExtraController.cs b/IRaCIS.Core.API/Controllers/ExtraController.cs index 034aac1c9..406959cc2 100644 --- a/IRaCIS.Core.API/Controllers/ExtraController.cs +++ b/IRaCIS.Core.API/Controllers/ExtraController.cs @@ -170,7 +170,9 @@ namespace IRaCIS.Api.Controllers } var userId = returnModel.Data.BasicInfo.Id.ToString(); - provider.Set(userId, userId, TimeSpan.FromMinutes(AppSettings.LoginExpiredTimeSpan)); + //provider.Set(userId, userId, TimeSpan.FromMinutes(AppSettings.LoginExpiredTimeSpan)); + + await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7)); return returnModel; } diff --git a/IRaCIS.Core.API/Controllers/UploadController.cs b/IRaCIS.Core.API/Controllers/UploadController.cs index 319f93ed1..4d143e12b 100644 --- a/IRaCIS.Core.API/Controllers/UploadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadController.cs @@ -1,6 +1,7 @@ using AutoMapper; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Filter; +using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infra.EFCore; @@ -205,10 +206,9 @@ namespace IRaCIS.Core.API.Controllers if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - //var fileNameEX = Path.GetExtension(fileRealName); - //var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; - var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileRealName; + var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(fileRealName); + relativePath = $"/{StaticData.SystemDataFolder}/{StaticData.DataTemplate}/{trustedFileNameForFileStorage}"; @@ -227,11 +227,9 @@ namespace IRaCIS.Core.API.Controllers if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - //var fileNameEX = Path.GetExtension(fileRealName); - //var fileName=Path.GetFileName(fileRealName); - //var trustedFileNameForFileStorage = fileName + Guid.NewGuid().ToString() + fileNameEX; + var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(fileRealName); + - var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileRealName; relativePath = $"/{StaticData.SystemDataFolder}/{StaticData.NoticeAttachment}/{trustedFileNameForFileStorage}"; @@ -271,11 +269,7 @@ namespace IRaCIS.Core.API.Controllers var uploadFolderPath = Path.Combine(_fileStorePath, trialId.ToString(), StaticData.SignDocumentFolder); if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); - - //var fileNameEX = Path.GetExtension(fileRealName); - //var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; - - var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileRealName; + var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(fileRealName); relativePath = $"/{StaticData.TrialDataFolder}/{trialId}/{StaticData.SignDocumentFolder}/{trustedFileNameForFileStorage}"; diff --git a/IRaCIS.Core.API/Program.cs b/IRaCIS.Core.API/Program.cs index 5ebcf881e..866d33353 100644 --- a/IRaCIS.Core.API/Program.cs +++ b/IRaCIS.Core.API/Program.cs @@ -43,7 +43,7 @@ namespace IRaCIS.Core.API NewId.SetProcessIdProvider(new CurrentProcessIdProvider()); - + //// Serilog SerilogExtension.AddSerilogSetup(environment, host.Services); diff --git a/IRaCIS.Core.API/Startup.cs b/IRaCIS.Core.API/Startup.cs index 869b55ee6..746c1106e 100644 --- a/IRaCIS.Core.API/Startup.cs +++ b/IRaCIS.Core.API/Startup.cs @@ -75,6 +75,9 @@ namespace IRaCIS.Core.API options.Filters.Add(); options.Filters.Add(); options.Filters.Add(); + + options.Filters.Add(); + }) .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => diff --git a/IRaCIS.Core.API/_ServiceExtensions/Authorization/ApiResponseHandler.cs b/IRaCIS.Core.API/_ServiceExtensions/Authorization/ApiResponseHandler.cs index 921c156e5..32f999568 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/Authorization/ApiResponseHandler.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/Authorization/ApiResponseHandler.cs @@ -24,14 +24,14 @@ namespace IRaCIS.Core.API { Response.ContentType = "application/json"; Response.StatusCode = StatusCodes.Status401Unauthorized; - await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您无权访问该接口"))); + await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您无权访问该接口", ApiResponseCodeEnum.NoToken))); } protected override async Task HandleForbiddenAsync(AuthenticationProperties properties) { Response.ContentType = "application/json"; Response.StatusCode = StatusCodes.Status403Forbidden; - await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您的权限不允许进行该操作"))); + await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您的权限不允许进行该操作",ApiResponseCodeEnum.HaveTokenNotAccess))); } } diff --git a/IRaCIS.Core.API/appsettings.Development.json b/IRaCIS.Core.API/appsettings.Development.json index 36f518b8f..6fcf52190 100644 --- a/IRaCIS.Core.API/appsettings.Development.json +++ b/IRaCIS.Core.API/appsettings.Development.json @@ -16,7 +16,9 @@ "OpenSignDocumentBeforeWork": false, - "OpenTrialRelationDelete": true + "OpenTrialRelationDelete": true, + + "OpenLoginLimit": true } diff --git a/IRaCIS.Core.API/appsettings.Production.json b/IRaCIS.Core.API/appsettings.Production.json index f867db9a5..e9df69ad1 100644 --- a/IRaCIS.Core.API/appsettings.Production.json +++ b/IRaCIS.Core.API/appsettings.Production.json @@ -14,7 +14,9 @@ "OpenUserComplexPassword": true, - "OpenSignDocumentBeforeWork": true + "OpenSignDocumentBeforeWork": true, + + "OpenLoginLimit": true } diff --git a/IRaCIS.Core.Application/BusinessFilter/LimitUserRequestAuthorization.cs b/IRaCIS.Core.Application/BusinessFilter/LimitUserRequestAuthorization.cs index 1426eaebc..b02e218fd 100644 --- a/IRaCIS.Core.Application/BusinessFilter/LimitUserRequestAuthorization.cs +++ b/IRaCIS.Core.Application/BusinessFilter/LimitUserRequestAuthorization.cs @@ -1,11 +1,13 @@ using EasyCaching.Core; using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; - -namespace IRaCIS.Core.Application.BusinessFilter; +namespace IRaCIS.Core.Application.Filter; @@ -18,66 +20,79 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter private readonly IUserInfo _userInfo; - public LimitUserRequestAuthorization(IEasyCachingProvider provider, IUserInfo userInfo) + private readonly IOptionsMonitor _verifyConfig; + + public LimitUserRequestAuthorization(IEasyCachingProvider provider, IUserInfo userInfo, IOptionsMonitor verifyConfig) { _provider = provider; _userInfo = userInfo; + _verifyConfig = verifyConfig; } public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { - if (context.ActionDescriptor.EndpointMetadata.Any(item => item is IAllowAnonymous)) + if (_verifyConfig.CurrentValue.OpenLoginLimit) { - //匿名访问的不处理 - } - else - { - //1、用户登陆的时候,设置缓存 - - - - //2、在这里取缓存 进行比较 看是否有其他人进行了登陆,如果其他人登陆了,就把之前用户挤掉 - - var cacheUserToken = (await _provider.GetAsync(_userInfo.Id.ToString())).Value; - - if (cacheUserToken == null) + if (context.ActionDescriptor.EndpointMetadata.Any(item => item is IAllowAnonymous)) { - //设置当前用户最新Token - await _provider.SetAsync(_userInfo.Id.ToString(), _userInfo.UserToken, TimeSpan.FromDays(7)); - - } - //是同一个人 - else if(cacheUserToken == _userInfo.UserToken) - { - + //匿名访问的不处理 } else { - context.Result = new StatusCodeResult(401); - } + //1、用户登陆的时候,设置缓存 - var cacheHostToken = (await _provider.GetAsync(_userInfo.IP.ToString()+_userInfo.LocalIp.ToString())).Value; - if (cacheHostToken == null) - { - //设置当前主机最新Token - await _provider.SetAsync(_userInfo.IP.ToString() + _userInfo.LocalIp.ToString(), _userInfo.UserToken, TimeSpan.FromDays(7)); + + //2、在这里取缓存 进行比较 看是否有其他人进行了登陆,如果其他人登陆了,就把之前用户挤掉 + + var cacheUserToken = (await _provider.GetAsync(_userInfo.Id.ToString())).Value; + + if (cacheUserToken == null) + { + //设置当前用户最新Token + await _provider.SetAsync(_userInfo.Id.ToString(), _userInfo.UserToken, TimeSpan.FromDays(7)); + + } + //是同一个人 + else if (cacheUserToken == _userInfo.UserToken) + { + + } + else + { + + context.HttpContext.Response.ContentType = "application/json"; + context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden; + await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您的账户在其他地方已登陆,您被迫下线", ApiResponseCodeEnum.LoginInOtherPlace))); + + //context.Result = new StatusCodeResult(401); + } + + //var cacheHostToken = (await _provider.GetAsync(_userInfo.IP.ToString()+_userInfo.LocalIp.ToString())).Value; + + //if (cacheHostToken == null) + //{ + // //设置当前主机最新Token + // await _provider.SetAsync(_userInfo.IP.ToString() + _userInfo.LocalIp.ToString(), _userInfo.UserToken, TimeSpan.FromDays(7)); + + //} + ////是同主机 + //else if (cacheHostToken == _userInfo.UserToken) + //{ + + //} + //else + //{ + // context.Result = new StatusCodeResult(401); + //} } - //是同主机 - else if (cacheHostToken == _userInfo.UserToken) - { - - } - else - { - context.Result = new StatusCodeResult(401); - } - } + + } -} +} @@ -92,39 +107,39 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter - //public class UserTypeRequirement : IAuthorizationRequirement - //{ - //} +//public class UserTypeRequirement : IAuthorizationRequirement +//{ +//} - //public class UserTypeHandler : AuthorizationHandler - //{ +//public class UserTypeHandler : AuthorizationHandler +//{ - // private IUserInfo _userInfo; +// private IUserInfo _userInfo; - // public UserTypeHandler(IUserInfo userInfo) - // { - // _userInfo = userInfo; - // } +// public UserTypeHandler(IUserInfo userInfo) +// { +// _userInfo = userInfo; +// } - // protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserTypeRequirement requirement) - // { +// protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserTypeRequirement requirement) +// { - // //if (context.User.Claims.Count() == 0) - // //{ - // // return Task.CompletedTask; - // //} +// //if (context.User.Claims.Count() == 0) +// //{ +// // return Task.CompletedTask; +// //} - // //string userId = context.User.Claims.First(c => c.Type == "Userid").Value; - // //string qq = context.User.Claims.First(c => c.Type == "QQ").Value; +// //string userId = context.User.Claims.First(c => c.Type == "Userid").Value; +// //string qq = context.User.Claims.First(c => c.Type == "QQ").Value; - // //if (_UserService.Validata(userId, qq)) - // //{ - // // context.Succeed(requirement); //验证通过了 - // //} - // ////在这里就可以做验证 +// //if (_UserService.Validata(userId, qq)) +// //{ +// // context.Succeed(requirement); //验证通过了 +// //} +// ////在这里就可以做验证 - // return Task.CompletedTask; - // } - //} +// return Task.CompletedTask; +// } +//} diff --git a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs new file mode 100644 index 000000000..76f3899ee --- /dev/null +++ b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs @@ -0,0 +1,29 @@ + + +namespace IRaCIS.Core.Application.Helper; + +public static class FileStoreHelper +{ + + + + public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName) + { + + //带目录层级,需要后端处理前端的路径 + if (fileName.Contains("\\")) + { + fileName = fileName.Split("\\").Last(); + } + + if (fileName.Contains("/")) + { + fileName = fileName.Split("/").Last(); + } + + var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileName; + + return (trustedFileNameForFileStorage, fileName); + } +} + diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 9b9bea5be..29b94c262 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -519,7 +519,7 @@ namespace IRaCIS.Application.Services } var success = await _userRepository.SaveChangesAsync(); - return ResponseOutput.Result(success); + return ResponseOutput.Ok(success); } diff --git a/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs b/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs index 4e54b0f18..8484ce835 100644 --- a/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs @@ -7,6 +7,9 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Hosting; using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Application.Helper; +using IRaCIS.Core.Infrastructure; +using IRaCIS.Core.Application.Service.Verify; namespace IRaCIS.Core.Application.Contracts { @@ -20,21 +23,25 @@ namespace IRaCIS.Core.Application.Contracts private readonly IRepository _previousHistoryRepository; private readonly IRepository _previousSurgeryRepository; private readonly IRepository _previousPdfRepository; - + private readonly IRepository _subjectVisitRepository; public ClinicalDataService(IRepository previousHistoryRepository, IRepository previousOtherRepository, IRepository previousSurgeryRepository, - IRepository previousPDFRepository) + IRepository previousPDFRepository, + IRepository subjectVisitRepository + ) { _previousOtherRepository = previousOtherRepository; _previousHistoryRepository = previousHistoryRepository; _previousSurgeryRepository = previousSurgeryRepository; _previousPdfRepository = previousPDFRepository; + _subjectVisitRepository = subjectVisitRepository; } + /// /// 上传临床数据 /// @@ -46,7 +53,7 @@ namespace IRaCIS.Core.Application.Contracts [DisableRequestSizeLimit] public async Task UploadVisitClinicalData(IFormCollection formCollection, Guid subjectVisitId, [FromServices] IWebHostEnvironment _hostEnvironment) { - + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).IfNullThrowException().FullName; @@ -65,9 +72,8 @@ namespace IRaCIS.Core.Application.Contracts foreach (IFormFile file in formCollection.Files) { - var realName = file.FileName; - var fileNameEX = Path.GetExtension(realName); - var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; + + var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(file.FileName); var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}"; @@ -80,7 +86,7 @@ namespace IRaCIS.Core.Application.Contracts } //插入临床pdf 路径 - await _previousPdfRepository.AddAsync(new PreviousPDF() { SubjectVisitId = subjectVisitId, Path = relativePath, FileName = realName }); + await _previousPdfRepository.AddAsync(new PreviousPDF() { SubjectVisitId = subjectVisitId, Path = relativePath, FileName = fileName }); } @@ -88,12 +94,7 @@ namespace IRaCIS.Core.Application.Contracts return ResponseOutput.Ok(); - //return ResponseOutput.Ok(new - //{ - // FilePath = relativePath, - // FullFilePath = relativePath + "?access_token=" + _userInfo.UserToken - //}); } @@ -156,15 +157,17 @@ namespace IRaCIS.Core.Application.Contracts [HttpPost("{trialId:guid}")] public async Task> AddOrUpdatePreviousHistory(PreviousHistoryAddOrEdit addOrEditPreviousHistory) { - + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousHistory.SubjectVisitId); + var entity = await _previousHistoryRepository.InsertOrUpdateAsync(addOrEditPreviousHistory, true); return ResponseOutput.Ok(entity.Id); } [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousHistoryId:guid}")] - public async Task DeletePreviousHistory(Guid previousHistoryId) - { + public async Task DeletePreviousHistory(Guid previousHistoryId,Guid subjectVisitId) + { + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); await _previousHistoryRepository.DeleteFromQueryAsync(t => t.Id == previousHistoryId,true); return ResponseOutput.Ok(); } @@ -180,7 +183,8 @@ namespace IRaCIS.Core.Application.Contracts [HttpPost("{trialId:guid}")] public async Task> AddOrUpdatePreviousOther(PreviousOtherAddOrEdit addOrEditPreviousOther) - { + { + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousOther.SubjectVisitId); var entity = await _previousOtherRepository.InsertOrUpdateAsync(addOrEditPreviousOther, true); return ResponseOutput.Ok(entity.Id); @@ -188,8 +192,10 @@ namespace IRaCIS.Core.Application.Contracts [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousOtherId:guid}")] - public async Task DeletePreviousOther(Guid previousOtherId) - { + public async Task DeletePreviousOther(Guid previousOtherId, Guid subjectVisitId) + { + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await _previousOtherRepository.DeleteFromQueryAsync(t => t.Id == previousOtherId,true); return ResponseOutput.Ok(); } @@ -206,15 +212,16 @@ namespace IRaCIS.Core.Application.Contracts [HttpPost("{trialId:guid}")] public async Task> AddOrUpdatePreviousSurgery(PreviousSurgeryAddOrEdit addOrEditPreviousSurgery) { - + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousSurgery.SubjectVisitId); var entity = await _previousSurgeryRepository.InsertOrUpdateAsync(addOrEditPreviousSurgery, true); return ResponseOutput.Ok(entity.Id); } [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousSurgeryId:guid}")] - public async Task DeletePreviousSurgery(Guid previousSurgeryId) + public async Task DeletePreviousSurgery(Guid previousSurgeryId, Guid subjectVisitId) { + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var success = await _previousSurgeryRepository.DeleteFromQueryAsync(t => t.Id == previousSurgeryId,true); return ResponseOutput.Ok(); } @@ -231,16 +238,17 @@ namespace IRaCIS.Core.Application.Contracts public async Task AddOrUpdatePreviousPDF(PreviousPDFAddOrEdit addOrEditPreviousPDF) { - + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousPDF.SubjectVisitId); var entity = await _previousPdfRepository.InsertOrUpdateAsync(addOrEditPreviousPDF, true); return ResponseOutput.Ok(entity.Id); } [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousPDFId:guid}")] - public async Task DeletePreviousPDF(Guid previousPDFId) + public async Task DeletePreviousPDF(Guid previousPDFId, Guid subjectVisitId) { - + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await _previousPdfRepository.DeleteFromQueryAsync(t => t.Id == previousPDFId,true); return ResponseOutput.Ok(); } diff --git a/IRaCIS.Core.Application/Service/QC/Interface/IClinicalDataService.cs b/IRaCIS.Core.Application/Service/QC/Interface/IClinicalDataService.cs index 41f154571..ac02d5d77 100644 --- a/IRaCIS.Core.Application/Service/QC/Interface/IClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/QC/Interface/IClinicalDataService.cs @@ -16,10 +16,10 @@ namespace IRaCIS.Core.Application.Contracts Task> AddOrUpdatePreviousOther(PreviousOtherAddOrEdit addOrEditPreviousOther); Task AddOrUpdatePreviousPDF(PreviousPDFAddOrEdit addOrEditPreviousPDF); Task> AddOrUpdatePreviousSurgery(PreviousSurgeryAddOrEdit addOrEditPreviousSurgery); - Task DeletePreviousHistory(Guid previousHistoryId); - Task DeletePreviousOther(Guid previousOtherId); - Task DeletePreviousPDF(Guid previousPDFId); - Task DeletePreviousSurgery(Guid previousSurgeryId); + Task DeletePreviousHistory(Guid previousHistoryId, Guid subjectVisitId); + Task DeletePreviousOther(Guid previousOtherId, Guid subjectVisitId); + Task DeletePreviousPDF(Guid previousPDFId, Guid subjectVisitId); + Task DeletePreviousSurgery(Guid previousSurgeryId, Guid subjectVisitId); Task> GetPreviousHistoryList(PreviousHistoryQuery queryPreviousHistory); Task> GetPreviousOtherList(PreviousOtherQuery queryPreviousOther); Task> GetPreviousPDFList(Guid subjectVisitId); diff --git a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs index 294b6a802..308615585 100644 --- a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs +++ b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs @@ -16,6 +16,8 @@ using IRaCIS.Application.Interfaces; using IRaCIS.Core.Infrastructure; using Microsoft.Extensions.Logging; using System.ComponentModel.DataAnnotations; +using IRaCIS.Core.Application.Helper; +using IRaCIS.Core.Application.Service.Verify; namespace IRaCIS.Core.Application.Contracts { @@ -57,18 +59,7 @@ namespace IRaCIS.Core.Application.Contracts } - private void VerifyIsCanQC(SubjectVisit? subjectVisit, Guid? sujectVisitId = null) - { - if (sujectVisitId != null) - { - subjectVisit = _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == sujectVisitId).Result.IfNullThrowException(); - } - if (subjectVisit!.CurrentActionUserId != _userInfo.Id) - { - throw new BusinessValidationFailedException("您不是该质控任务当前领取人,没有操作权限!"); - } - } [HttpGet] public async Task> GetNoneDicomStudyList( [FromQuery,NotDefault] Guid subjectVisitId,Guid? nonedicomStudyId) @@ -133,7 +124,9 @@ namespace IRaCIS.Core.Application.Contracts if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC) { - VerifyIsCanQC(null, addOrEditNoneDicomStudy.SubjectVisitId); + + await QCCommonVerify.VerifyIsCanQCAsync(_repository, _userInfo, null, addOrEditNoneDicomStudy.SubjectVisitId); + } optEntity = await _noneDicomStudyRepository.UpdateFromDTOAsync(addOrEditNoneDicomStudy); @@ -157,11 +150,9 @@ namespace IRaCIS.Core.Application.Contracts public async Task DeleteNoneDicomStudy(Guid noneDicomStudyId, Guid subjectVisitId) { //提交了 但是IQC同意的时候 是可以删除的 | 普通提交后也不能删除 - if (await _subjectVisitRepository.AnyAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.Submitted && - (!t.QCChallengeList.Any(u => u.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload)))) - { - return ResponseOutput.NotOk("CRC Has Submited Image,can not delete"); - } + + + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository,_userInfo, subjectVisitId); await _noneDicomStudyRepository.DeleteFromQueryAsync(noneDicomStudyId); @@ -181,12 +172,7 @@ namespace IRaCIS.Core.Application.Contracts public async Task DeleteNoneDicomStudyFile(Guid noneDicomStudyFileId, Guid subjectVisitId) { //提交了 但是IQC同意的时候 是可以删除的 | 普通提交后也不能删除 - if (await _subjectVisitRepository.AnyAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.Submitted && - (!t.QCChallengeList.Any(u => u.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload)))) - { - return ResponseOutput.NotOk("CRC Has Submited Image,can not delete"); - } - //var subjectVisitId = await _noneDicomStudyFileRepository.Where(t => t.Id == noneDicomStudyFileId).Select(t => t.NoneDicomStudy.SubjectVisitId).FirstOrDefaultAsync(); + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var success = await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.Id == noneDicomStudyFileId, true); @@ -227,6 +213,8 @@ namespace IRaCIS.Core.Application.Contracts [TypeFilter(typeof(TrialResourceFilter))] public async Task UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId) { + await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).IfNullThrowException().FullName; //上传根路径 @@ -262,7 +250,9 @@ namespace IRaCIS.Core.Application.Contracts - var( trustedFileNameForFileStorage, fileName) = GetStoreFileName(file.FileName); + + var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(file.FileName); + var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}"; var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); @@ -305,36 +295,11 @@ namespace IRaCIS.Core.Application.Contracts return ResponseOutput.Ok(/*list*/); } - private (string TrustedFileNameForFileStorage,string RealName ) GetStoreFileName(string fileName) - { - //var realName = fileName; - //var fileNameEX = Path.GetExtension(realName); - - //var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; - - - //带目录层级,需要后端处理前端的路径 - if (fileName.Contains("\\")) - { - fileName = fileName.Split("\\").Last(); - } - - if (fileName.Contains("/")) - { - fileName = fileName.Split("/").Last(); - } - - - - var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileName; - - return (trustedFileNameForFileStorage, fileName); - } private async void DealCompressFile(IArchiveEntry entry, dynamic sv, Guid subjectVisitId, Guid noneDicomStudyId, string uploadFolderPath) { - var (trustedFileNameForFileStorage, fileName) = GetStoreFileName(entry.Key); + var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(entry.Key); var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}"; diff --git a/IRaCIS.Core.Application/Service/QC/QCCommonVerify.cs b/IRaCIS.Core.Application/Service/QC/QCCommonVerify.cs new file mode 100644 index 000000000..b6d38edf0 --- /dev/null +++ b/IRaCIS.Core.Application/Service/QC/QCCommonVerify.cs @@ -0,0 +1,39 @@ +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure; + + +namespace IRaCIS.Core.Application.Service.Verify +{ + public static class QCCommonVerify + { + + public static async Task VerifyIsCRCSubmmitAsync(IRepository _repository, IUserInfo _userInfo, Guid? subjectVisitId=null) + { + //添加的时候不验证 + if (subjectVisitId != null) + { + if (await _repository.AnyAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.Submitted && + (!t.QCChallengeList.Any(u => u.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload)))) + { + throw new BusinessValidationFailedException("CRC 已提交影像,不能进行操作。"); + } + } + + + } + + public static async Task VerifyIsCanQCAsync(IRepository _repository,IUserInfo _userInfo, SubjectVisit? subjectVisit=null, Guid? subjectVisitId=null) + { + if (subjectVisitId != null) + { + subjectVisit = (await _repository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException(); + } + + if (subjectVisit!.CurrentActionUserId != _userInfo.Id) + { + throw new BusinessValidationFailedException("您不是该质控任务当前领取人,没有操作权限!"); + } + } + + } +} diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs index 2bc97ef7e..10bc10625 100644 --- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs @@ -1354,7 +1354,10 @@ namespace IRaCIS.Core.Application.Image.QA dbSubjectVisit.SubmitTime = DateTime.Now; } - + else + { + return ResponseOutput.NotOk("当前访视的影像数据,已经由其他CRC提交。"); + } //不审 直接QC通过 可能一致性核查 也可能不一致性核查 if (trialConfig.QCProcessEnum == TrialQCProcess.NotAudit) { @@ -1373,8 +1376,6 @@ namespace IRaCIS.Core.Application.Image.QA else if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit) { dbSubjectVisit.AuditState = AuditStateEnum.ToAudit; - - } @@ -1382,7 +1383,8 @@ namespace IRaCIS.Core.Application.Image.QA var success = await _repository.SaveChangesAsync(); - return ResponseOutput.Result(success); + + return ResponseOutput.Ok(success); diff --git a/IRaCIS.Core.Domain.Share/ServiceVerifyConfigOption.cs b/IRaCIS.Core.Domain.Share/ServiceVerifyConfigOption.cs index dfab0be70..16d3ab2af 100644 --- a/IRaCIS.Core.Domain.Share/ServiceVerifyConfigOption.cs +++ b/IRaCIS.Core.Domain.Share/ServiceVerifyConfigOption.cs @@ -13,5 +13,7 @@ namespace IRaCIS.Core.Domain.Share public bool OpenTrialRelationDelete { get; set; } + + public bool OpenLoginLimit { get; set; } } } \ No newline at end of file diff --git a/IRaCIS.Core.Infrastructure/Extention/Output/ApiResponseCodeEnum.cs b/IRaCIS.Core.Infrastructure/Extention/Output/ApiResponseCodeEnum.cs index 504649ee6..4963e0e1e 100644 --- a/IRaCIS.Core.Infrastructure/Extention/Output/ApiResponseCodeEnum.cs +++ b/IRaCIS.Core.Infrastructure/Extention/Output/ApiResponseCodeEnum.cs @@ -24,7 +24,17 @@ namespace IRaCIS.Core.Infrastructure.Extention ProgramException = 4, //需要提示 ,需要提示 从Result 取数据 - NeedTips = 5 + NeedTips = 5, + + + //在其他地方登陆,被迫下线 + LoginInOtherPlace = -1, + + //没有带token访问(未登陆) + NoToken=10, + + //带了Token,但是没有相应权限(该用户类型不能做) + HaveTokenNotAccess=11 }