diff --git a/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java b/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java index 60f14d5816f78292cae24dae42bed45619263a35..637208277cf6e33451ecf75cc448c98dadb3e073 100644 --- a/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java +++ b/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java @@ -6,12 +6,12 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.auth.TokenPrincipal; +import it.inaf.ia2.transfer.exception.PermissionDeniedException; import it.inaf.ia2.transfer.service.ArchiveJob; import it.inaf.ia2.transfer.service.ArchiveJob.Type; import it.inaf.ia2.transfer.service.ArchiveService; import java.io.File; import java.util.concurrent.CompletableFuture; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; @@ -30,9 +30,6 @@ public class ArchiveFileController extends FileController { @Autowired private ArchiveService archiveService; - @Autowired - private HttpServletRequest request; - @Autowired private HttpServletResponse response; @@ -42,7 +39,7 @@ public class ArchiveFileController extends FileController { Type type = Type.valueOf(archiveRequest.getType()); ArchiveJob job = new ArchiveJob(); - job.setPrincipal((TokenPrincipal) request.getUserPrincipal()); + job.setPrincipal(getPrincipal()); job.setJobId(archiveRequest.getJobId()); job.setType(type); job.setVosPaths(archiveRequest.getPaths()); @@ -59,10 +56,20 @@ public class ArchiveFileController extends FileController { @GetMapping(value = "/archive/{fileName}") public void getArchiveFile(@PathVariable("fileName") String fileName) { - TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal(); + TokenPrincipal principal = getPrincipal(); File file = archiveService.getArchiveParentDir(principal).toPath().resolve(fileName).toFile(); FileResponseUtil.getFileResponse(response, file); } + + private TokenPrincipal getPrincipal() { + TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal(); + + if ("anonymous".equals(principal.getName())) { + throw new PermissionDeniedException("Tar/Zip archive generation not allowed to anonymous users"); + } + + return principal; + } } diff --git a/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java b/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java index 2b2d41dea7278de88a79f45016af6fe6bb94edd9..bc8cbd1b406221db81ad0eb1e288f873cf752147 100644 --- a/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java +++ b/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java @@ -65,7 +65,7 @@ public class GetFileController extends FileController { FileInfo fileInfo = optFileInfo.get(); if (!authorizationService.isDownloadable(fileInfo, (TokenPrincipal) request.getUserPrincipal())) { - throw new PermissionDeniedException(path); + throw new PermissionDeniedException("PermissionDenied Path: " + path); } File file = new File(fileInfo.getOsPath()); diff --git a/src/main/java/it/inaf/ia2/transfer/exception/PermissionDeniedException.java b/src/main/java/it/inaf/ia2/transfer/exception/PermissionDeniedException.java index 357f69b62cf659c1ca9e1570535ae5ade05168a6..6658bc8791a6e442c51229c075099b7fb53a2a6c 100644 --- a/src/main/java/it/inaf/ia2/transfer/exception/PermissionDeniedException.java +++ b/src/main/java/it/inaf/ia2/transfer/exception/PermissionDeniedException.java @@ -11,8 +11,8 @@ import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(value = HttpStatus.FORBIDDEN) public class PermissionDeniedException extends JobException { - public PermissionDeniedException(String path) { + public PermissionDeniedException(String errorDetail) { super(Type.FATAL, "Permission Denied"); - setErrorDetail("PermissionDenied Path: " + path); + setErrorDetail(errorDetail); } } diff --git a/src/test/java/it/inaf/ia2/transfer/controller/ArchiveFileControllerTest.java b/src/test/java/it/inaf/ia2/transfer/controller/ArchiveFileControllerTest.java index e353fdf61100e57d6b2820d74a68a6ab20d391b9..b5d04fd65b28c6dbbd2843e3b4c80cc3d284d1bf 100644 --- a/src/test/java/it/inaf/ia2/transfer/controller/ArchiveFileControllerTest.java +++ b/src/test/java/it/inaf/ia2/transfer/controller/ArchiveFileControllerTest.java @@ -6,26 +6,34 @@ package it.inaf.ia2.transfer.controller; import com.fasterxml.jackson.databind.ObjectMapper; +import it.inaf.ia2.transfer.auth.TokenPrincipal; import it.inaf.ia2.transfer.service.ArchiveJob; import it.inaf.ia2.transfer.service.ArchiveService; +import java.io.File; +import java.nio.file.Files; import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import org.springframework.util.FileSystemUtils; @SpringBootTest -@AutoConfigureMockMvc +@AutoConfigureMockMvc(addFilters = false) public class ArchiveFileControllerTest { private static final ObjectMapper MAPPER = new ObjectMapper(); @@ -45,6 +53,7 @@ public class ArchiveFileControllerTest { request.setPaths(Arrays.asList("/path/to/file1", "/path/to/file2")); mockMvc.perform(post("/archive") + .principal(fakePrincipal("user1")) .contentType(MediaType.APPLICATION_JSON) .content(MAPPER.writeValueAsString(request))) .andDo(print()) @@ -53,9 +62,60 @@ public class ArchiveFileControllerTest { verify(archiveService, times(1)).createArchive(argThat(job -> { assertEquals("123", job.getJobId()); assertEquals(ArchiveJob.Type.TAR, job.getType()); - assertEquals("anonymous", job.getPrincipal().getName()); + assertEquals("user1", job.getPrincipal().getName()); assertEquals(2, job.getVosPaths().size()); return true; })); } + + @Test + public void testGetArchive() throws Exception { + + File tmpDir = Files.createTempDirectory("tmp").toFile(); + + try { + tmpDir.toPath().resolve("123.zip").toFile().createNewFile(); + + when(archiveService.getArchiveParentDir(any())).thenReturn(tmpDir); + + mockMvc.perform(get("/archive/123.zip") + .principal(fakePrincipal("user1"))) + .andDo(print()) + .andExpect(status().isOk()); + + } finally { + FileSystemUtils.deleteRecursively(tmpDir); + } + } + + @Test + public void testAnonymousCantCreateArchive() throws Exception { + + ArchiveRequest request = new ArchiveRequest(); + request.setJobId("123"); + request.setType("ZIP"); + request.setPaths(Arrays.asList("/ignore")); + + mockMvc.perform(post("/archive") + .principal(fakePrincipal("anonymous")) + .contentType(MediaType.APPLICATION_JSON) + .content(MAPPER.writeValueAsString(request))) + .andDo(print()) + .andExpect(status().isForbidden()); + } + + @Test + public void testAnonymousCantGetArchive() throws Exception { + + mockMvc.perform(get("/archive/123.zip") + .principal(fakePrincipal("anonymous"))) + .andDo(print()) + .andExpect(status().isForbidden()); + } + + private TokenPrincipal fakePrincipal(String name) { + TokenPrincipal principal = mock(TokenPrincipal.class); + when(principal.getName()).thenReturn(name); + return principal; + } }