Loading src/main/java/es/redmic/ApiApplication.java +7 −2 Original line number Diff line number Diff line package es.redmic; import java.util.List; /*- * #%L * API Loading Loading @@ -47,6 +49,7 @@ import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import es.redmic.api.common.converter.QueryDTOMessageConverter; import es.redmic.api.config.GenerateJsonSchemaScanBean; import es.redmic.api.config.ResourceBundleMessageSource; import es.redmic.api.utils.filters.DTOFilters; import es.redmic.databaselib.common.repository.BaseRepositoryImpl; import es.redmic.db.config.EntityManagerWrapper; import es.redmic.es.common.service.UserUtilsServiceItfc; Loading Loading @@ -106,8 +109,10 @@ public class ApiApplication { @Bean public QueryDTOMessageConverter queryDTOMessageConverter() { FilterProvider filters = new SimpleFilterProvider().setFailOnUnknownId(false).addFilter("DataQueryDTO", SimpleBeanPropertyFilter.serializeAll()); FilterProvider filters = new SimpleFilterProvider().setFailOnUnknownId(false) .addFilter("DataQueryDTO", SimpleBeanPropertyFilter.serializeAll()) .addFilter("InternalDocumentFilter", DTOFilters.getDocumentFilter(userService)); objectMapper.setFilterProvider(filters); return new QueryDTOMessageConverter(objectMapper, userService); Loading src/main/java/es/redmic/api/utils/filters/DTOFilters.java 0 → 100644 +71 −0 Original line number Diff line number Diff line package es.redmic.api.utils.filters; /*- * #%L * API * %% * Copyright (C) 2019 - 2022 REDMIC Project / Server * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.util.List; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import es.redmic.es.common.service.UserUtilsServiceItfc; import es.redmic.models.es.administrative.dto.DocumentDTO; public class DTOFilters { public static SimpleBeanPropertyFilter getDocumentFilter(UserUtilsServiceItfc userService) { return new SimpleBeanPropertyFilter() { @Override public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception { if (include(writer)) { List<String> roles = userService.getUserRole(); if (writer.getName().equals("internalUrl")) { setInternalUrlFilter((DocumentDTO) pojo, roles); } writer.serializeAsField(pojo, jgen, provider); } else if (!jgen.canOmitFields()) { // since 2.3 writer.serializeAsOmittedField(pojo, jgen, provider); } } @Override protected boolean include(BeanPropertyWriter writer) { return true; } @Override protected boolean include(PropertyWriter writer) { return true; } }; } private static void setInternalUrlFilter(DocumentDTO document, List<String> roles) { Boolean privateInternalUrl = document.getPrivateInternalUrl(); if (!roles.contains("ROLE_ADMINISTRATOR") && Boolean.TRUE.equals(privateInternalUrl)) { document.setInternalUrl(null); } } } src/test/java/es/redmic/test/integration/administrative/DocumentControllerTest.java 0 → 100644 +161 −0 Original line number Diff line number Diff line package es.redmic.test.integration.administrative; /*- * #%L * API * %% * Copyright (C) 2019 - 2022 REDMIC Project / Server * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.notNullValue; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.http.MediaType; import org.springframework.restdocs.JUnitRestDocumentation; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import com.fasterxml.jackson.databind.ObjectMapper; import es.redmic.ApiApplication; import es.redmic.es.administrative.repository.DocumentESRepository; import es.redmic.models.es.administrative.model.Document; import es.redmic.models.es.common.model.DomainES; import es.redmic.models.es.common.query.dto.MetadataQueryDTO; import es.redmic.test.integration.common.IntegrationTestBase; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = { ApiApplication.class }, webEnvironment = WebEnvironment.RANDOM_PORT) @ActiveProfiles("test") public class DocumentControllerTest extends IntegrationTestBase { @Rule public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets"); @Value("${controller.mapping.DOCUMENT}") private String CONTROLLER_DOCUMENT; @Autowired ObjectMapper mapper; @Autowired DocumentESRepository repository; private RestDocumentationResultHandler document; Document modelToIndex; @Override @Before public void setUp() { // @formatter:off this.document = document("{class-name}/{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())); mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(springSecurityFilterChain) .apply(documentationConfiguration(this.restDocumentation)).alwaysDo(this.document).build(); modelToIndex = new Document(); modelToIndex.setId(33L); modelToIndex.setCode("ext-3"); modelToIndex.setYear("2000"); modelToIndex.setAuthor("Fulanito"); modelToIndex.setLanguage("es"); modelToIndex.setTitle("Sólo para administradores"); modelToIndex.setSource("Esto es un documento en español"); modelToIndex.setInternalUrl("/api/mediastorage/123.pdf"); modelToIndex.setPrivateInternalUrl(true); DomainES documentType = new DomainES(); documentType.setId(1L); documentType.setName("Artículo de revista"); documentType.setName_en("..."); modelToIndex.setDocumentType(documentType); modelToIndex = repository.save(modelToIndex); // @formatter:on } @Test public void checkDocumentController_ReturnInternalUrl_IfSearchDocumentAsAdminUser() throws Exception { MetadataQueryDTO query = new MetadataQueryDTO(); query.setSize(1); String content = mapper.writeValueAsString(query); ResultActions result = this.mockMvc .perform(post(CONTROLLER_DOCUMENT + "/_search").content(content) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + getTokenAdministratorUser())); result.andExpect(status().is2xxSuccessful()); result.andExpect(jsonPath("$.body.data[0].internalUrl", notNullValue())); } @Test public void checkDocumentController_NoReturnInternalUrl_IfSearchDocumentAsUserAndPrivateInternalUrlIsTrue() throws Exception { MetadataQueryDTO query = new MetadataQueryDTO(); query.setSize(1); ResultActions result = this.mockMvc .perform(post(CONTROLLER_DOCUMENT + "/_search").content(mapper.writeValueAsString(query)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + getTokenUser())); result.andExpect(status().is2xxSuccessful()); result.andExpect(jsonPath("$.body.data[0].internalUrl", nullValue())); } @Test public void checkDocumentController_ReturnInternalUrl_IfSearchDocumentAsUserAndPrivateInternalUrlIsFalse() throws Exception { MetadataQueryDTO query = new MetadataQueryDTO(); query.setSize(1); modelToIndex.setPrivateInternalUrl(false); modelToIndex = repository.save(modelToIndex); ResultActions result = this.mockMvc .perform(post(CONTROLLER_DOCUMENT + "/_search").content(mapper.writeValueAsString(query)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + getTokenUser())); result.andExpect(status().is2xxSuccessful()); result.andExpect(jsonPath("$.body.data[0].internalUrl", notNullValue())); } } Loading
src/main/java/es/redmic/ApiApplication.java +7 −2 Original line number Diff line number Diff line package es.redmic; import java.util.List; /*- * #%L * API Loading Loading @@ -47,6 +49,7 @@ import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import es.redmic.api.common.converter.QueryDTOMessageConverter; import es.redmic.api.config.GenerateJsonSchemaScanBean; import es.redmic.api.config.ResourceBundleMessageSource; import es.redmic.api.utils.filters.DTOFilters; import es.redmic.databaselib.common.repository.BaseRepositoryImpl; import es.redmic.db.config.EntityManagerWrapper; import es.redmic.es.common.service.UserUtilsServiceItfc; Loading Loading @@ -106,8 +109,10 @@ public class ApiApplication { @Bean public QueryDTOMessageConverter queryDTOMessageConverter() { FilterProvider filters = new SimpleFilterProvider().setFailOnUnknownId(false).addFilter("DataQueryDTO", SimpleBeanPropertyFilter.serializeAll()); FilterProvider filters = new SimpleFilterProvider().setFailOnUnknownId(false) .addFilter("DataQueryDTO", SimpleBeanPropertyFilter.serializeAll()) .addFilter("InternalDocumentFilter", DTOFilters.getDocumentFilter(userService)); objectMapper.setFilterProvider(filters); return new QueryDTOMessageConverter(objectMapper, userService); Loading
src/main/java/es/redmic/api/utils/filters/DTOFilters.java 0 → 100644 +71 −0 Original line number Diff line number Diff line package es.redmic.api.utils.filters; /*- * #%L * API * %% * Copyright (C) 2019 - 2022 REDMIC Project / Server * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.util.List; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import es.redmic.es.common.service.UserUtilsServiceItfc; import es.redmic.models.es.administrative.dto.DocumentDTO; public class DTOFilters { public static SimpleBeanPropertyFilter getDocumentFilter(UserUtilsServiceItfc userService) { return new SimpleBeanPropertyFilter() { @Override public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception { if (include(writer)) { List<String> roles = userService.getUserRole(); if (writer.getName().equals("internalUrl")) { setInternalUrlFilter((DocumentDTO) pojo, roles); } writer.serializeAsField(pojo, jgen, provider); } else if (!jgen.canOmitFields()) { // since 2.3 writer.serializeAsOmittedField(pojo, jgen, provider); } } @Override protected boolean include(BeanPropertyWriter writer) { return true; } @Override protected boolean include(PropertyWriter writer) { return true; } }; } private static void setInternalUrlFilter(DocumentDTO document, List<String> roles) { Boolean privateInternalUrl = document.getPrivateInternalUrl(); if (!roles.contains("ROLE_ADMINISTRATOR") && Boolean.TRUE.equals(privateInternalUrl)) { document.setInternalUrl(null); } } }
src/test/java/es/redmic/test/integration/administrative/DocumentControllerTest.java 0 → 100644 +161 −0 Original line number Diff line number Diff line package es.redmic.test.integration.administrative; /*- * #%L * API * %% * Copyright (C) 2019 - 2022 REDMIC Project / Server * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.notNullValue; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.http.MediaType; import org.springframework.restdocs.JUnitRestDocumentation; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import com.fasterxml.jackson.databind.ObjectMapper; import es.redmic.ApiApplication; import es.redmic.es.administrative.repository.DocumentESRepository; import es.redmic.models.es.administrative.model.Document; import es.redmic.models.es.common.model.DomainES; import es.redmic.models.es.common.query.dto.MetadataQueryDTO; import es.redmic.test.integration.common.IntegrationTestBase; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = { ApiApplication.class }, webEnvironment = WebEnvironment.RANDOM_PORT) @ActiveProfiles("test") public class DocumentControllerTest extends IntegrationTestBase { @Rule public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets"); @Value("${controller.mapping.DOCUMENT}") private String CONTROLLER_DOCUMENT; @Autowired ObjectMapper mapper; @Autowired DocumentESRepository repository; private RestDocumentationResultHandler document; Document modelToIndex; @Override @Before public void setUp() { // @formatter:off this.document = document("{class-name}/{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())); mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(springSecurityFilterChain) .apply(documentationConfiguration(this.restDocumentation)).alwaysDo(this.document).build(); modelToIndex = new Document(); modelToIndex.setId(33L); modelToIndex.setCode("ext-3"); modelToIndex.setYear("2000"); modelToIndex.setAuthor("Fulanito"); modelToIndex.setLanguage("es"); modelToIndex.setTitle("Sólo para administradores"); modelToIndex.setSource("Esto es un documento en español"); modelToIndex.setInternalUrl("/api/mediastorage/123.pdf"); modelToIndex.setPrivateInternalUrl(true); DomainES documentType = new DomainES(); documentType.setId(1L); documentType.setName("Artículo de revista"); documentType.setName_en("..."); modelToIndex.setDocumentType(documentType); modelToIndex = repository.save(modelToIndex); // @formatter:on } @Test public void checkDocumentController_ReturnInternalUrl_IfSearchDocumentAsAdminUser() throws Exception { MetadataQueryDTO query = new MetadataQueryDTO(); query.setSize(1); String content = mapper.writeValueAsString(query); ResultActions result = this.mockMvc .perform(post(CONTROLLER_DOCUMENT + "/_search").content(content) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + getTokenAdministratorUser())); result.andExpect(status().is2xxSuccessful()); result.andExpect(jsonPath("$.body.data[0].internalUrl", notNullValue())); } @Test public void checkDocumentController_NoReturnInternalUrl_IfSearchDocumentAsUserAndPrivateInternalUrlIsTrue() throws Exception { MetadataQueryDTO query = new MetadataQueryDTO(); query.setSize(1); ResultActions result = this.mockMvc .perform(post(CONTROLLER_DOCUMENT + "/_search").content(mapper.writeValueAsString(query)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + getTokenUser())); result.andExpect(status().is2xxSuccessful()); result.andExpect(jsonPath("$.body.data[0].internalUrl", nullValue())); } @Test public void checkDocumentController_ReturnInternalUrl_IfSearchDocumentAsUserAndPrivateInternalUrlIsFalse() throws Exception { MetadataQueryDTO query = new MetadataQueryDTO(); query.setSize(1); modelToIndex.setPrivateInternalUrl(false); modelToIndex = repository.save(modelToIndex); ResultActions result = this.mockMvc .perform(post(CONTROLLER_DOCUMENT + "/_search").content(mapper.writeValueAsString(query)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + getTokenUser())); result.andExpect(status().is2xxSuccessful()); result.andExpect(jsonPath("$.body.data[0].internalUrl", notNullValue())); } }