-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[JN-1409] Document library [participant UX] #1369
Changes from all commits
a0f5551
f240681
d34eb58
b280158
2ba4f02
bfad334
75823f7
f183fe1
dd4292e
ca01c31
6fe550f
dedfd52
0db38ce
cda4ce5
19a99c1
92f8cbc
3be449b
67a593a
38723d6
06b0e95
0874a9f
d6d0d40
f47fdc8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package bio.terra.pearl.api.participant.controller.file; | ||
|
||
import bio.terra.pearl.api.participant.api.ParticipantFileApi; | ||
import bio.terra.pearl.api.participant.service.RequestUtilService; | ||
import bio.terra.pearl.api.participant.service.file.ParticipantFileExtService; | ||
import bio.terra.pearl.core.model.EnvironmentName; | ||
import bio.terra.pearl.core.model.file.ParticipantFile; | ||
import bio.terra.pearl.core.model.participant.ParticipantUser; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import java.io.InputStream; | ||
import java.util.List; | ||
import org.springframework.core.io.InputStreamResource; | ||
import org.springframework.core.io.Resource; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@Controller | ||
public class ParticipantFileController implements ParticipantFileApi { | ||
private final ParticipantFileExtService participantFileExtService; | ||
private final HttpServletRequest request; | ||
private final ObjectMapper objectMapper; | ||
private final RequestUtilService requestUtilService; | ||
|
||
public ParticipantFileController( | ||
ParticipantFileExtService participantFileExtService, | ||
HttpServletRequest request, | ||
ObjectMapper objectMapper, | ||
RequestUtilService requestUtilService) { | ||
this.participantFileExtService = participantFileExtService; | ||
this.request = request; | ||
this.objectMapper = objectMapper; | ||
this.requestUtilService = requestUtilService; | ||
} | ||
|
||
@Override | ||
public ResponseEntity<Resource> download( | ||
String portalShortcode, | ||
String envName, | ||
String studyShortcode, | ||
String enrolleeShortcode, | ||
String fileName) { | ||
ParticipantUser participantUser = requestUtilService.requireUser(request); | ||
|
||
ParticipantFile participantFile = | ||
participantFileExtService.get( | ||
portalShortcode, | ||
EnvironmentName.valueOf(envName), | ||
participantUser, | ||
enrolleeShortcode, | ||
fileName); | ||
|
||
InputStream content = | ||
participantFileExtService.downloadFile( | ||
portalShortcode, | ||
EnvironmentName.valueOf(envName), | ||
participantUser, | ||
enrolleeShortcode, | ||
fileName); | ||
|
||
MediaType mediaType; | ||
try { | ||
mediaType = MediaType.parseMediaType(participantFile.getFileType()); | ||
} catch (Exception e) { | ||
mediaType = MediaType.APPLICATION_OCTET_STREAM; | ||
} | ||
|
||
return ResponseEntity.ok().contentType(mediaType).body(new InputStreamResource(content)); | ||
} | ||
|
||
@Override | ||
public ResponseEntity<Object> upload( | ||
String portalShortcode, | ||
String envName, | ||
String studyShortcode, | ||
String enrolleeShortcode, | ||
MultipartFile participantFile) { | ||
ParticipantUser participantUser = requestUtilService.requireUser(request); | ||
|
||
ParticipantFile created = | ||
participantFileExtService.uploadFile( | ||
portalShortcode, | ||
EnvironmentName.valueOf(envName), | ||
participantUser, | ||
enrolleeShortcode, | ||
participantFile); | ||
|
||
return ResponseEntity.ok(created); | ||
} | ||
|
||
@Override | ||
public ResponseEntity<Object> list( | ||
String portalShortcode, String envName, String studyShortcode, String enrolleeShortcode) { | ||
ParticipantUser participantUser = requestUtilService.requireUser(request); | ||
|
||
List<ParticipantFile> participantFiles = | ||
participantFileExtService.list( | ||
portalShortcode, EnvironmentName.valueOf(envName), participantUser, enrolleeShortcode); | ||
return ResponseEntity.ok(participantFiles); | ||
} | ||
|
||
@Override | ||
public ResponseEntity<Object> delete( | ||
String portalShortcode, | ||
String envName, | ||
String studyShortcode, | ||
String enrolleeShortcode, | ||
String fileName) { | ||
ParticipantUser participantUser = requestUtilService.requireUser(request); | ||
|
||
participantFileExtService.delete( | ||
portalShortcode, | ||
EnvironmentName.valueOf(envName), | ||
participantUser, | ||
enrolleeShortcode, | ||
fileName); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package bio.terra.pearl.api.participant.service.file; | ||
|
||
import bio.terra.pearl.api.participant.service.AuthUtilService; | ||
import bio.terra.pearl.core.model.EnvironmentName; | ||
import bio.terra.pearl.core.model.file.ParticipantFile; | ||
import bio.terra.pearl.core.model.participant.Enrollee; | ||
import bio.terra.pearl.core.model.participant.ParticipantUser; | ||
import bio.terra.pearl.core.service.exception.NotFoundException; | ||
import bio.terra.pearl.core.service.file.ParticipantFileService; | ||
import bio.terra.pearl.core.service.file.backends.FileStorageBackend; | ||
import bio.terra.pearl.core.service.file.backends.FileStorageBackendProvider; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.util.List; | ||
import java.util.Set; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@Service | ||
@Slf4j | ||
public class ParticipantFileExtService { | ||
|
||
private final ParticipantFileService participantFileService; | ||
private final AuthUtilService authUtilService; | ||
private final FileStorageBackend fileStorageBackend; | ||
|
||
public ParticipantFileExtService( | ||
ParticipantFileService participantFileService, | ||
AuthUtilService authUtilService, | ||
FileStorageBackendProvider fileStorageBackendProvider) { | ||
this.participantFileService = participantFileService; | ||
this.authUtilService = authUtilService; | ||
this.fileStorageBackend = fileStorageBackendProvider.get(); | ||
} | ||
|
||
public ParticipantFile get( | ||
String portalShortcode, | ||
EnvironmentName envName, | ||
ParticipantUser participantUser, | ||
String enrolleeShortcode, | ||
String fileName) { | ||
authUtilService.authParticipantToPortal(participantUser.getId(), portalShortcode, envName); | ||
Enrollee enrollee = | ||
authUtilService.authParticipantUserToEnrollee(participantUser.getId(), enrolleeShortcode); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't have permissions on the PArticipantApi, but we probably should eventually move to annotation-based auth like the admin tool so logic like this gets more foolproof and easier to test. I'll make a ticket |
||
return participantFileService | ||
.findByEnrolleeIdAndFileName(enrollee.getId(), fileName) | ||
.orElseThrow(() -> new NotFoundException("Could not find file")); | ||
} | ||
|
||
public InputStream downloadFile( | ||
String portalShortcode, | ||
EnvironmentName envName, | ||
ParticipantUser participantUser, | ||
String enrolleeShortcode, | ||
String fileName) { | ||
authUtilService.authParticipantToPortal(participantUser.getId(), portalShortcode, envName); | ||
Enrollee enrollee = | ||
authUtilService.authParticipantUserToEnrollee(participantUser.getId(), enrolleeShortcode); | ||
ParticipantFile participantFile = | ||
participantFileService | ||
.findByEnrolleeIdAndFileName(enrollee.getId(), fileName) | ||
.orElseThrow(() -> new NotFoundException("Could not find file")); | ||
|
||
return fileStorageBackend.downloadFile(participantFile.getExternalFileId()); | ||
} | ||
|
||
public ParticipantFile uploadFile( | ||
String portalShortcode, | ||
EnvironmentName envName, | ||
ParticipantUser participantUser, | ||
String enrolleeShortcode, | ||
MultipartFile file) { | ||
authUtilService.authParticipantToPortal(participantUser.getId(), portalShortcode, envName); | ||
Enrollee enrollee = | ||
authUtilService.authParticipantUserToEnrollee(participantUser.getId(), enrolleeShortcode); | ||
|
||
try { | ||
return participantFileService.uploadFileAndCreate( | ||
ParticipantFile.builder() | ||
.enrolleeId(enrollee.getId()) | ||
.fileName(getFileName(file.getOriginalFilename())) | ||
.fileType(file.getContentType()) | ||
.build(), | ||
file.getInputStream()); | ||
} catch (IOException e) { | ||
throw new RuntimeException("Error uploading file"); | ||
} | ||
} | ||
|
||
public List<ParticipantFile> list( | ||
String portalShortcode, | ||
EnvironmentName envName, | ||
ParticipantUser participantUser, | ||
String enrolleeShortcode) { | ||
authUtilService.authParticipantToPortal(participantUser.getId(), portalShortcode, envName); | ||
Enrollee enrollee = | ||
authUtilService.authParticipantUserToEnrollee(participantUser.getId(), enrolleeShortcode); | ||
return participantFileService.findByEnrolleeId(enrollee.getId()); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this method could use a comment and possibly a rename, since I at first thought it was doing something similar to the cleanFileName in SiteContentImage. |
||
// Returns the name of the file without the preceding path | ||
public String getFileName(String fileName) { | ||
if (fileName == null) { | ||
return ""; | ||
} | ||
String[] split = fileName.split("\\[/\\\\]"); | ||
return split[split.length - 1]; | ||
} | ||
|
||
public void delete( | ||
String portalShortcode, | ||
EnvironmentName envName, | ||
ParticipantUser participantUser, | ||
String enrolleeShortcode, | ||
String fileName) { | ||
authUtilService.authParticipantToPortal(participantUser.getId(), portalShortcode, envName); | ||
Enrollee enrollee = | ||
authUtilService.authParticipantUserToEnrollee(participantUser.getId(), enrolleeShortcode); | ||
ParticipantFile participantFile = | ||
participantFileService | ||
.findByEnrolleeIdAndFileName(enrollee.getId(), fileName) | ||
.orElseThrow(() -> new NotFoundException("Could not find file")); | ||
|
||
participantFileService.delete(participantFile.getId(), Set.of()); | ||
fileStorageBackend.deleteFile(participantFile.getExternalFileId()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh also, I think we should do a check to verify that the participant is in this study env