Skip to content

Commit 3b231af

Browse files
committed
P4ADEV-2238 fix download file permission
1 parent 4fd646b commit 3b231af

File tree

5 files changed

+107
-11
lines changed

5 files changed

+107
-11
lines changed

src/main/java/it/gov/pagopa/pu/fileshare/service/export/ExportFileFacadeServiceImpl.java

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import org.apache.commons.lang3.StringUtils;
1717
import org.springframework.core.io.InputStreamResource;
18+
import org.springframework.security.authorization.AuthorizationDeniedException;
1819
import org.springframework.stereotype.Service;
1920

2021
@Service
@@ -47,6 +48,10 @@ public FileResourceDTO downloadExportFile(Long organizationId,
4748
"Export file with id %s was not found".formatted(exportFileId));
4849
}
4950

51+
if(!organizationId.equals(exportFile.getOrganizationId())){
52+
throw new AuthorizationDeniedException("Access Denied");
53+
}
54+
5055
if (!AuthorizationService.isAdminRole(organizationId, user) &&
5156
!user.getMappedExternalUserId()
5257
.equals(exportFile.getOperatorExternalId())) {

src/main/java/it/gov/pagopa/pu/fileshare/service/ingestion/IngestionFlowFileFacadeServiceImpl.java

+13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import it.gov.pagopa.pu.fileshare.dto.generated.IngestionFlowFileType;
88
import it.gov.pagopa.pu.fileshare.exception.custom.FileAlreadyExistsException;
99
import it.gov.pagopa.pu.fileshare.exception.custom.FileNotFoundException;
10+
import it.gov.pagopa.pu.fileshare.exception.custom.UnauthorizedFileDownloadException;
1011
import it.gov.pagopa.pu.fileshare.mapper.IngestionFlowFileDTOMapper;
12+
import it.gov.pagopa.pu.fileshare.service.AuthorizationService;
1113
import it.gov.pagopa.pu.fileshare.service.FileService;
1214
import it.gov.pagopa.pu.fileshare.service.FileStorerService;
1315
import it.gov.pagopa.pu.fileshare.service.UserAuthorizationService;
@@ -17,6 +19,7 @@
1719
import lombok.extern.slf4j.Slf4j;
1820
import org.springframework.beans.factory.annotation.Value;
1921
import org.springframework.core.io.InputStreamResource;
22+
import org.springframework.security.authorization.AuthorizationDeniedException;
2023
import org.springframework.stereotype.Service;
2124
import org.springframework.web.multipart.MultipartFile;
2225

@@ -88,6 +91,16 @@ public FileResourceDTO downloadIngestionFlowFile(Long organizationId, Long inges
8891
throw new FileNotFoundException("Ingestion flow file with id %s was not found".formatted(ingestionFlowFileId));
8992
}
9093

94+
if(!organizationId.equals(ingestionFlowFile.getOrganizationId())){
95+
throw new AuthorizationDeniedException("Access Denied");
96+
}
97+
98+
if (!AuthorizationService.isAdminRole(organizationId, user) &&
99+
!user.getMappedExternalUserId().equals(ingestionFlowFile.getOperatorExternalId())) {
100+
throw new UnauthorizedFileDownloadException(
101+
"User is not authorized to download ingestion flow file with ID " + ingestionFlowFileId);
102+
}
103+
91104
Path filePath = getFilePath(ingestionFlowFile);
92105

93106
InputStream decryptedInputStream = fileStorerService.decryptFile(filePath, ingestionFlowFile.getFileName());

src/test/java/it/gov/pagopa/pu/fileshare/service/export/ExportFileFacadeServiceImplTest.java

+33
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.mockito.Mock;
2323
import org.mockito.Mockito;
2424
import org.mockito.junit.jupiter.MockitoExtension;
25+
import org.springframework.security.authorization.AuthorizationDeniedException;
2526

2627
@ExtendWith(MockitoExtension.class)
2728
class ExportFileFacadeServiceImplTest {
@@ -94,6 +95,38 @@ void givenAuthorizedUserWhenDownloadExportFileThenReturnFileResource() {
9495
Mockito.verify(fileStorerServiceMock).decryptFile(fullFilePath, fileName);
9596
}
9697

98+
@Test
99+
void givenUnauthorizedOrganizationWhenDownloadExportFileThenThrowException() {
100+
String accessToken = "TOKEN";
101+
Long organizationId = 1L;
102+
Long exportFileId = 10L;
103+
String filePathName = "examplePath";
104+
String fileName = "testFile.zip";
105+
106+
UserOrganizationRoles userTestRole = new UserOrganizationRoles();
107+
userTestRole.setRoles(List.of("TEST"));
108+
userTestRole.setOrganizationId(organizationId);
109+
UserInfo user = new UserInfo();
110+
user.setOrganizations(List.of(userTestRole));
111+
user.setMappedExternalUserId("UNAUTHORIZED_OPERATOR");
112+
113+
ExportFile exportFile = new ExportFile();
114+
exportFile.setOrganizationId(-1L);
115+
exportFile.setFileName(fileName);
116+
exportFile.setFilePathName(filePathName);
117+
exportFile.setStatus(ExportFile.StatusEnum.COMPLETED);
118+
exportFile.setOperatorExternalId("TEST");
119+
120+
Mockito.when(exportFileServiceMock.getExportFile(exportFileId, accessToken)).thenReturn(exportFile);
121+
122+
Executable exec = () -> exportFileService.downloadExportFile(organizationId, exportFileId, user, accessToken);
123+
124+
Assertions.assertThrows(AuthorizationDeniedException.class, exec);
125+
126+
Mockito.verify(userAuthorizationServiceMock).checkUserAuthorization(organizationId, user, accessToken);
127+
Mockito.verify(exportFileServiceMock).getExportFile(exportFileId, accessToken);
128+
}
129+
97130
@Test
98131
void givenUnauthorizedUserWhenDownloadExportFileThenThrowException() {
99132
String accessToken = "TOKEN";

src/test/java/it/gov/pagopa/pu/fileshare/service/ingestion/IngestionFlowFileFacadeServiceImplTest.java

+43-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import it.gov.pagopa.pu.fileshare.dto.generated.FileOrigin;
77
import it.gov.pagopa.pu.fileshare.dto.generated.IngestionFlowFileType;
88
import it.gov.pagopa.pu.fileshare.exception.custom.FileAlreadyExistsException;
9+
import it.gov.pagopa.pu.fileshare.exception.custom.UnauthorizedFileDownloadException;
910
import it.gov.pagopa.pu.fileshare.mapper.IngestionFlowFileDTOMapper;
1011
import it.gov.pagopa.pu.fileshare.service.FileService;
1112
import it.gov.pagopa.pu.fileshare.service.FileStorerService;
@@ -25,6 +26,7 @@
2526
import org.mockito.junit.jupiter.MockitoExtension;
2627
import org.springframework.http.MediaType;
2728
import org.springframework.mock.web.MockMultipartFile;
29+
import org.springframework.security.authorization.AuthorizationDeniedException;
2830

2931
import java.io.ByteArrayInputStream;
3032
import java.io.InputStream;
@@ -203,7 +205,7 @@ void givenAuthorizedUserWhenDownloadIngestionFlowFileThenReturnFileResource() {
203205
String fileName = "testFile.zip";
204206
Path fullFilePath = organizationBasePath.resolve(filePathName).resolve(ARCHIVED_SUB_FOLDER);
205207

206-
UserInfo user = TestUtils.getSampleUser();
208+
UserInfo user = TestUtils.getSampleAdminUser();
207209

208210
IngestionFlowFile ingestionFlowFile = new IngestionFlowFile();
209211
ingestionFlowFile.setOrganizationId(organizationId);
@@ -230,6 +232,45 @@ void givenAuthorizedUserWhenDownloadIngestionFlowFileThenReturnFileResource() {
230232
Mockito.verify(fileStorerServiceMock).decryptFile(fullFilePath, fileName);
231233
}
232234

235+
@Test
236+
void givenUnauthorizedOrganizationWhenDownloadIngestionFlowFileThenThrowAuthorizationDeniedException() {
237+
String accessToken = "TOKEN";
238+
Long organizationId = 1L;
239+
Long ingestionFlowFileId = 10L;
240+
241+
UserInfo user = TestUtils.getSampleAdminUser();
242+
243+
IngestionFlowFile ingestionFlowFile = new IngestionFlowFile();
244+
ingestionFlowFile.setOrganizationId(-1L);
245+
ingestionFlowFile.setStatus(IngestionFlowFile.StatusEnum.COMPLETED);
246+
247+
Mockito.when(ingestionFlowFileServiceMock.getIngestionFlowFile(ingestionFlowFileId, accessToken)).thenReturn(ingestionFlowFile);
248+
249+
Assertions.assertThrows(AuthorizationDeniedException.class, () -> ingestionFlowFileService.downloadIngestionFlowFile(organizationId, ingestionFlowFileId, user, accessToken));
250+
251+
Mockito.verify(userAuthorizationServiceMock).checkUserAuthorization(organizationId, user, accessToken);
252+
}
253+
254+
@Test
255+
void givenUnauthorizedUserWhenDownloadIngestionFlowFileThenThrowAuthorizationDeniedException() {
256+
String accessToken = "TOKEN";
257+
Long organizationId = 1L;
258+
Long ingestionFlowFileId = 10L;
259+
260+
UserInfo user = TestUtils.getSampleUser();
261+
262+
IngestionFlowFile ingestionFlowFile = new IngestionFlowFile();
263+
ingestionFlowFile.setOrganizationId(1L);
264+
ingestionFlowFile.setOperatorExternalId("OTHERUSER");
265+
ingestionFlowFile.setStatus(IngestionFlowFile.StatusEnum.COMPLETED);
266+
267+
Mockito.when(ingestionFlowFileServiceMock.getIngestionFlowFile(ingestionFlowFileId, accessToken)).thenReturn(ingestionFlowFile);
268+
269+
Assertions.assertThrows(UnauthorizedFileDownloadException.class, () -> ingestionFlowFileService.downloadIngestionFlowFile(organizationId, ingestionFlowFileId, user, accessToken));
270+
271+
Mockito.verify(userAuthorizationServiceMock).checkUserAuthorization(organizationId, user, accessToken);
272+
}
273+
233274
@Test
234275
void givenIngestionFlowFileInProgressWhenDownloadIngestionFlowFileThenReturnFilePath() {
235276
String accessToken = "TOKEN";
@@ -240,7 +281,7 @@ void givenIngestionFlowFileInProgressWhenDownloadIngestionFlowFileThenReturnFile
240281
String fileName = "testFile.zip";
241282
Path fullFilePath = organizationBasePath.resolve(filePathName);
242283

243-
UserInfo user = TestUtils.getSampleUser();
284+
UserInfo user = TestUtils.getSampleAdminUser();
244285

245286
IngestionFlowFile ingestionFlowFile = new IngestionFlowFile();
246287
ingestionFlowFile.setOrganizationId(organizationId);

src/test/java/it/gov/pagopa/pu/fileshare/util/TestUtils.java

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package it.gov.pagopa.pu.fileshare.util;
22

3+
import it.gov.pagopa.pu.fileshare.service.AuthorizationService;
34
import it.gov.pagopa.pu.p4paauth.dto.generated.UserInfo;
45
import it.gov.pagopa.pu.p4paauth.dto.generated.UserOrganizationRoles;
5-
import java.util.Arrays;
6-
import java.util.Collection;
7-
import java.util.HashSet;
8-
import java.util.List;
9-
import java.util.Set;
106
import org.junit.jupiter.api.Assertions;
117
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
128
import org.springframework.security.core.GrantedAuthority;
139
import org.springframework.security.core.authority.SimpleGrantedAuthority;
1410
import org.springframework.security.core.context.SecurityContextHolder;
1511

12+
import java.util.*;
13+
1614
public class TestUtils {
1715

1816
private TestUtils(){}
@@ -45,22 +43,28 @@ public static void addSampleUserIntoSecurityContext(){
4543
SecurityContextHolder.getContext().setAuthentication(authToken);
4644
}
4745

46+
public static UserInfo getSampleAdminUser(){
47+
return getSampleUser(true, AuthorizationService.ROLE_ADMIN);
48+
}
49+
4850
public static UserInfo getSampleUser(){
49-
return getSampleUser(true);
51+
return getSampleUser(true, "ROLE_OPER");
5052
}
5153

52-
public static UserInfo getSampleUser(Boolean organizationAccess){
54+
public static UserInfo getSampleUser(Boolean organizationAccess, String role){
5355
List<UserOrganizationRoles> organizations = List.of(
5456
new UserOrganizationRoles()
5557
.operatorId("operator1")
58+
.organizationId(1L)
5659
.organizationIpaCode("ORG")
5760
58-
.roles(List.of("ROLE")),
61+
.roles(List.of(role)),
5962
new UserOrganizationRoles()
6063
.operatorId("operator2")
64+
.organizationId(2L)
6165
.organizationIpaCode("ORG2")
6266
63-
.roles(List.of("ROLE2"))
67+
.roles(List.of(role))
6468
);
6569
return new UserInfo().mappedExternalUserId("MAPPEDEXTERNALUSERID")
6670
.fiscalCode("FISCALCODE")

0 commit comments

Comments
 (0)