Skip to content
Snippets Groups Projects
Commit 00cd8b0b authored by Tobias Bruns's avatar Tobias Bruns
Browse files

OZG-6986 add new role 'DATENBEAUFTRAGUNG'

parent 561cbbcd
Branches
Tags
1 merge request!3Ozg 6988 add reporting
package de.ozgcloud.admin;
import java.util.Optional;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.Path;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.core.mapping.PropertyAwareResourceMapping;
import org.springframework.data.rest.core.mapping.RepositoryResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceDescription;
import org.springframework.data.rest.core.mapping.ResourceMapping;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
import org.springframework.data.rest.core.mapping.SearchResourceMappings;
import org.springframework.data.rest.core.mapping.SupportedHttpMethods;
import org.springframework.hateoas.LinkRelation;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.method.SecuredAuthorizationManager;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.util.SimpleMethodInvocation;
import de.ozgcloud.common.errorhandling.TechnicalException;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Configuration
class OzgCloudRestLinksConfiguration {
@Primary
@Bean
RepositoryResourceMappings ozgCloudResourceMappings(Repositories repositories, PersistentEntities persistentEntities,
RepositoryRestConfiguration repositoryRestConfiguration) {
return new OzgCloudDelegatingRepositoryResourceMappings(repositories, persistentEntities, repositoryRestConfiguration);
}
}
@Log4j2
class OzgCloudDelegatingRepositoryResourceMappings extends RepositoryResourceMappings {
private final Repositories repositories;
private final SecuredAuthorizationManager authManager = new SecuredAuthorizationManager();
public OzgCloudDelegatingRepositoryResourceMappings(Repositories repositories, PersistentEntities entities,
RepositoryRestConfiguration configuration) {
super(repositories, entities, configuration);
this.repositories = repositories;
}
@Override
public ResourceMetadata getMetadataFor(Class<?> type) {
return new OzgCloudDelegatingResourceMetadata(super.getMetadataFor(type), repositories);
}
@RequiredArgsConstructor
class OzgCloudDelegatingResourceMetadata implements ResourceMetadata {
private final ResourceMetadata metadata;
private final Repositories repositories;
@Override
public LinkRelation getItemResourceRel() {
return metadata.getItemResourceRel();
}
@Override
public ResourceDescription getItemResourceDescription() {
return metadata.getItemResourceDescription();
}
@Override
public Optional<Class<?>> getExcerptProjection() {
return metadata.getExcerptProjection();
}
@Override
public boolean isExported() {
return isAccessPermitted(metadata.getDomainType()) && metadata.isExported();
}
boolean isAccessPermitted(Class<?> type) {
var repository = repositories.getRepositoryFor(type);
return repository.map(repo -> authManager.check(() -> SecurityContextHolder.getContext().getAuthentication(), getFindAllInvocation(repo)))
.map(AuthorizationDecision::isGranted)
.orElse(false);
}
MethodInvocation getFindAllInvocation(Object repository) {
try {
var method = repository.getClass().getMethod("findAll");
return new SimpleMethodInvocation(repository, method);
} catch (NoSuchMethodException | SecurityException e) {
LOG.error(e.getMessage(), e);
throw new TechnicalException("Error on extracting findAll Repository Method", e);
}
}
@Override
public LinkRelation getRel() {
return metadata.getRel();
}
@Override
public Path getPath() {
return metadata.getPath();
}
@Override
public boolean isPagingResource() {
return metadata.isPagingResource();
}
@Override
public ResourceDescription getDescription() {
return metadata.getDescription();
}
@Override
public Class<?> getDomainType() {
return metadata.getDomainType();
}
@Override
public boolean isExported(PersistentProperty<?> property) {
return metadata.isExported(property);
}
@Override
public PropertyAwareResourceMapping getProperty(String mappedPath) {
return metadata.getProperty(mappedPath);
}
@Override
public ResourceMapping getMappingFor(PersistentProperty<?> property) {
return metadata.getMappingFor(property);
}
@Override
public SearchResourceMappings getSearchResourceMappings() {
return metadata.getSearchResourceMappings();
}
@Override
public SupportedHttpMethods getSupportedHttpMethods() {
return metadata.getSupportedHttpMethods();
}
}
}
......@@ -28,5 +28,6 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UserRole {
public static final String DATENBEAUFTRAGUNG = "DATENBEAUFTRAGUNG";
public static final String ADMIN_ADMIN = "ADMIN_ADMIN";
}
......@@ -5,7 +5,9 @@ import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.security.access.annotation.Secured;
@Secured("ROLE_DATENBEAUFTRAGUNG")
@RepositoryRestResource
interface AggregationMappingRepository extends MongoRepository<AggregationMapping, String> {
@Override
......
......@@ -61,8 +61,10 @@ public class SecurityConfiguration {
http.authorizeHttpRequests(requests -> requests
.requestMatchers(HttpMethod.GET, "/api/environment").permitAll()
.requestMatchers("/api/configuration").hasRole(UserRole.ADMIN_ADMIN)
.requestMatchers("/api/configuration/**").hasRole(UserRole.ADMIN_ADMIN)
// .requestMatchers("/api/configuration").hasRole(UserRole.DATENBEAUFTRAGUNG)
// .requestMatchers("/api/configuration/**").hasRole(UserRole.DATENBEAUFTRAGUNG)
.requestMatchers("/api/configuration").hasAnyRole(UserRole.ADMIN_ADMIN, UserRole.DATENBEAUFTRAGUNG)
.requestMatchers("/api/configuration/**").hasAnyRole(UserRole.ADMIN_ADMIN, UserRole.DATENBEAUFTRAGUNG)
.requestMatchers("/api").authenticated()
.requestMatchers("/api/**").authenticated()
.requestMatchers("/actuator").permitAll()
......
......@@ -6,6 +6,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
......@@ -14,12 +15,13 @@ import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import de.ozgcloud.admin.common.user.UserRole;
import de.ozgcloud.common.test.DataITCase;
import de.ozgcloud.common.test.TestUtils;
import lombok.SneakyThrows;
@AutoConfigureMockMvc
@WithMockUser(roles = "ADMIN_ADMIN")
@WithMockUser(roles = "DATENBEAUFTRAGUNG")
@DataITCase
class ReportingSettingITCase {
......@@ -36,12 +38,21 @@ class ReportingSettingITCase {
@Test
@SneakyThrows
void shouldHaveLinkToReporting() {
void shouldHaveLinkToAggregationMapping() {
mockMvc.perform(get("/api/configuration"))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("$._links.aggregationMappings").exists());
}
@Test
@SneakyThrows
@WithMockUser(roles = UserRole.ADMIN_ADMIN)
void shouldNotHaveLinkOnMissingRole() {
mockMvc.perform(get("/api/configuration"))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("$._links.aggregationMappings").doesNotExist());
}
@Test
@SneakyThrows
void shouldDenyWhileMissingFields() {
......@@ -50,9 +61,20 @@ class ReportingSettingITCase {
.andExpect(status().isUnprocessableEntity());
}
@Disabled("is returning 500")
@Test
@SneakyThrows
@WithMockUser(roles = UserRole.ADMIN_ADMIN)
void shouldNotAllowAddingMapping() {
mockMvc.perform(post("/api/configuration/aggregationMappings").with(csrf())
.contentType(MediaType.APPLICATION_JSON).content(TestUtils.loadTextFile("reporting/request.json")))
.andExpect(status().is(403));
}
@Test
@SneakyThrows
void shouldAddReportingSetting() {
@WithMockUser(roles = "DATENBEAUFTRAGUNG")
void shouldAddAggregationMappings() {
mockMvc.perform(post("/api/configuration/aggregationMappings").with(csrf())
.contentType(MediaType.APPLICATION_JSON).content(TestUtils.loadTextFile("reporting/request.json")))
.andExpect(status().isCreated());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment