Skip to content
Snippets Groups Projects
Commit c9a1f2cd authored by Felix Reichenbach's avatar Felix Reichenbach
Browse files

OZG-6986 dont show configurations Link on missing permission

parent 19c96dfe
No related branches found
No related tags found
1 merge request!5Ozg 6986 fix configurations link
......@@ -33,6 +33,7 @@ import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.stereotype.Component;
import de.ozgcloud.admin.common.user.CurrentUserService;
import lombok.RequiredArgsConstructor;
@Component
......@@ -41,6 +42,7 @@ public class RootModelAssembler implements RepresentationModelAssembler<Root, En
static final String REL_CONFIGURATION = "configuration";
private final RepositoryRestProperties restProperties;
private final CurrentUserService currentUserService;
@Override
public EntityModel<Root> toModel(Root root) {
......@@ -52,7 +54,9 @@ public class RootModelAssembler implements RepresentationModelAssembler<Root, En
List<Link> links = new ArrayList<>();
var rootLinkBuilder = WebMvcLinkBuilder.linkTo(RootController.class);
links.add(rootLinkBuilder.withSelfRel());
links.add(buildConfigLink());
if (currentUserService.hasConfigurationPermission()) {
links.add(buildConfigLink());
}
return links;
}
......
......@@ -26,9 +26,10 @@ package de.ozgcloud.admin.common.user;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
......@@ -46,20 +47,25 @@ class CurrentUserHelper {
private static final Predicate<Authentication> IS_TRUSTED = auth -> !TRUST_RESOLVER.isAnonymous(auth);
public static boolean hasRole(String role) {
return hasAnyRole(Set.of(role));
}
public static boolean hasAnyRole(Set<String> roles) {
var auth = getAuthentication();
if ((Objects.isNull(auth)) || (Objects.isNull(auth.getPrincipal()))) {
return false;
}
return containsRole(auth.getAuthorities(), role);
return containsAnyRole(auth.getAuthorities(), roles);
}
static boolean containsRole(Collection<? extends GrantedAuthority> authorities, String role) {
static boolean containsAnyRole(Collection<? extends GrantedAuthority> authorities, Set<String> roles) {
if (Objects.isNull(authorities)) {
return false;
}
return authorities.stream().anyMatch(a -> StringUtils.equalsIgnoreCase(addRolePrefixIfMissing(role), a.getAuthority()));
var rolesWithPrefix = roles.stream().map(CurrentUserHelper::addRolePrefixIfMissing).collect(Collectors.toSet());
return authorities.stream().anyMatch(a -> rolesWithPrefix.contains(a.getAuthority()));
}
static String addRolePrefixIfMissing(String roleToCheck) {
......
......@@ -30,4 +30,8 @@ public class CurrentUserService {
public boolean hasRole(String role) {
return CurrentUserHelper.hasRole(role);
}
public boolean hasConfigurationPermission() {
return CurrentUserHelper.hasAnyRole(UserRole.CONFIGURATION_ROLES);
}
}
......@@ -23,6 +23,8 @@
*/
package de.ozgcloud.admin.common.user;
import java.util.Set;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
......@@ -30,4 +32,6 @@ import lombok.NoArgsConstructor;
public class UserRole {
public static final String DATENBEAUFTRAGUNG = "DATENBEAUFTRAGUNG";
public static final String ADMIN_ADMIN = "ADMIN_ADMIN";
public static final Set<String> CONFIGURATION_ROLES = Set.of(ADMIN_ADMIN, DATENBEAUFTRAGUNG);
}
......@@ -25,6 +25,7 @@ package de.ozgcloud.admin;
import static de.ozgcloud.admin.RootModelAssembler.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.util.List;
......@@ -34,34 +35,38 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.springframework.boot.autoconfigure.data.rest.RepositoryRestProperties;
import org.springframework.hateoas.Link;
import de.ozgcloud.admin.common.user.CurrentUserService;
class RootModelAssemblerTest {
private static final String BASE_PATH = "/api/base";
@Spy
@InjectMocks
private RootModelAssembler modelAssembler;
@Mock
private RepositoryRestProperties restProperties;
@Mock
private CurrentUserService currentUserService;
@DisplayName("Entity Model")
@Nested
class TestEntityModel {
@BeforeEach
void beforeEach() {
Mockito.when(restProperties.getBasePath()).thenReturn(BASE_PATH);
when(restProperties.getBasePath()).thenReturn(BASE_PATH);
}
@Test
void shouldHaveRoot() {
var givenRoot = RootTestFactory.create();
List<Link> links = List.of();
Mockito.when(modelAssembler.buildRootModelLinks()).thenReturn(links);
when(modelAssembler.buildRootModelLinks()).thenReturn(links);
var resultRoot = modelAssembler.toModel(givenRoot).getContent();
......@@ -71,7 +76,7 @@ class RootModelAssemblerTest {
@Test
void shouldHaveLinks() {
List<Link> links = List.of(Link.of(RootController.PATH));
Mockito.when(modelAssembler.buildRootModelLinks()).thenReturn(links);
when(modelAssembler.buildRootModelLinks()).thenReturn(links);
var modelLinks = modelAssembler.toModel(RootTestFactory.create()).getLinks();
......@@ -84,14 +89,46 @@ class RootModelAssemblerTest {
class TestBuildRootModelLinks {
@Test
void shouldHaveHrefToBasePathIfAuthorized() {
Mockito.when(restProperties.getBasePath()).thenReturn(BASE_PATH);
void shouldCheckConfigurationPermission() {
modelAssembler.buildRootModelLinks();
verify(currentUserService).hasConfigurationPermission();
}
@Nested
class TestOnHasConfigurationPermission {
@BeforeEach
void hasConfigurationPermission() {
when(currentUserService.hasConfigurationPermission()).thenReturn(true);
when(restProperties.getBasePath()).thenReturn(BASE_PATH);
}
@Test
void shouldHaveHrefToConfiguration() {
var links = modelAssembler.buildRootModelLinks();
assertThat(links).containsExactly(
Link.of(RootController.PATH),
Link.of(BASE_PATH, REL_CONFIGURATION));
}
}
@Nested
class TestOnNotHasConfigurationPermission {
@BeforeEach
void hasNotConfigurationPermission() {
when(currentUserService.hasConfigurationPermission()).thenReturn(false);
}
List<Link> links = modelAssembler.buildRootModelLinks();
@Test
void shouldHaveOnlySelfLink() {
var links = modelAssembler.buildRootModelLinks();
assertThat(links).containsExactly(
Link.of(RootController.PATH),
Link.of(BASE_PATH, REL_CONFIGURATION));
assertThat(links).containsExactly(
Link.of(RootController.PATH));
}
}
}
......
......@@ -24,9 +24,11 @@
package de.ozgcloud.admin.common.user;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
......@@ -35,7 +37,6 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
......@@ -43,23 +44,58 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import com.thedeanda.lorem.LoremIpsum;
class CurrentUserHelperTest {
@DisplayName("Has role")
@Nested
class TestHasRole {
@Mock
private final Authentication mockAuthentication = Mockito.mock(Authentication.class);
private Authentication mockAuthentication;
@Mock
private User mockPrincipal;
private final String role = LoremIpsum.getInstance().getWords(1);
@Test
void shouldCallHasAnyRole() {
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class, CALLS_REAL_METHODS)) {
mockUserHelper.when(() -> CurrentUserHelper.hasAnyRole(any())).thenReturn(false);
CurrentUserHelper.hasRole(role);
mockUserHelper.verify(() -> CurrentUserHelper.hasAnyRole(Set.of(role)));
}
}
@ParameterizedTest
@ValueSource(booleans = { false, true })
void shouldReturnValue(boolean hasRole) {
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class, CALLS_REAL_METHODS)) {
mockUserHelper.when(() -> CurrentUserHelper.hasAnyRole(any())).thenReturn(hasRole);
var result = CurrentUserHelper.hasRole(UserRole.ADMIN_ADMIN);
assertThat(result).isEqualTo(hasRole);
}
}
}
@Nested
class TestHasAnyRole {
@Mock
private Authentication mockAuthentication;
@Mock
private final User mockPrincipal = Mockito.mock(User.class);
private User mockPrincipal;
private final Set<String> roles = Set.of(LoremIpsum.getInstance().getWords(1));
@Test
void shouldReturnFalseOnMissingAuthentication() {
try (MockedStatic<CurrentUserHelper> mockUserHelper = Mockito.mockStatic(
CurrentUserHelper.class,
Mockito.CALLS_REAL_METHODS)) {
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class)) {
mockUserHelper.when(CurrentUserHelper::getAuthentication).thenReturn(null);
boolean hasRole = CurrentUserHelper.hasRole(UserRole.ADMIN_ADMIN);
boolean hasRole = CurrentUserHelper.hasAnyRole(roles);
assertThat(hasRole).isFalse();
}
......@@ -67,66 +103,72 @@ class CurrentUserHelperTest {
@Test
void shouldReturnFalseOnMissingPrincipal() {
Mockito.when(mockAuthentication.getPrincipal()).thenReturn(null);
try (MockedStatic<CurrentUserHelper> mockUserHelper = Mockito.mockStatic(
CurrentUserHelper.class,
Mockito.CALLS_REAL_METHODS)) {
when(mockAuthentication.getPrincipal()).thenReturn(null);
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class, CALLS_REAL_METHODS)) {
mockUserHelper.when(CurrentUserHelper::getAuthentication).thenReturn(mockAuthentication);
boolean hasRole = CurrentUserHelper.hasRole(UserRole.ADMIN_ADMIN);
boolean hasRole = CurrentUserHelper.hasAnyRole(roles);
assertThat(hasRole).isFalse();
}
}
@Test
void shouldCallContainsAnyRole() {
when(mockAuthentication.getPrincipal()).thenReturn(mockPrincipal);
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class, CALLS_REAL_METHODS)) {
mockUserHelper.when(CurrentUserHelper::getAuthentication).thenReturn(mockAuthentication);
CurrentUserHelper.hasAnyRole(roles);
mockUserHelper.verify(() -> CurrentUserHelper.containsAnyRole(mockAuthentication.getAuthorities(), roles));
}
}
@ParameterizedTest
@ValueSource(booleans = {false, true})
void shouldReturnValue(boolean containsRoleValue) {
Mockito.when(mockAuthentication.getPrincipal()).thenReturn(mockPrincipal);
List<GrantedAuthority> authorities = List.of();
Mockito.<Collection<? extends GrantedAuthority>>when(mockAuthentication.getAuthorities()).thenReturn(authorities);
try (MockedStatic<CurrentUserHelper> mockUserHelper = Mockito.mockStatic(
CurrentUserHelper.class,
Mockito.CALLS_REAL_METHODS)) {
@ValueSource(booleans = { false, true })
void shouldReturnValue(boolean hasRole) {
when(mockAuthentication.getPrincipal()).thenReturn(mockPrincipal);
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class, CALLS_REAL_METHODS)) {
mockUserHelper.when(CurrentUserHelper::getAuthentication).thenReturn(mockAuthentication);
mockUserHelper.when(() -> CurrentUserHelper.containsRole(Mockito.anyList(), Mockito.anyString()))
.thenReturn(containsRoleValue);
mockUserHelper.when(() -> CurrentUserHelper.containsAnyRole(any(), any())).thenReturn(hasRole);
boolean hasRole = CurrentUserHelper.hasRole(UserRole.ADMIN_ADMIN);
var result = CurrentUserHelper.hasAnyRole(roles);
mockUserHelper.verify(() -> CurrentUserHelper.containsRole(mockAuthentication.getAuthorities(), UserRole.ADMIN_ADMIN));
assertThat(hasRole).isEqualTo(containsRoleValue);
assertThat(result).isEqualTo(hasRole);
}
}
}
@DisplayName("Contains role")
@Nested
class TestContainsRole {
class TestContainsAnyRole {
@Test
void shouldNotContainRoleIfAuthoritiesIsNull() {
boolean containsRole = CurrentUserHelper.containsRole(null, UserRole.ADMIN_ADMIN);
void shouldReturnFalseIfAuthoritiesIsNull() {
boolean containsRole = CurrentUserHelper.containsAnyRole(null, Set.of(LoremIpsum.getInstance().getWords(1)));
assertThat(containsRole).isFalse();
}
@Test
void shouldNotContainRole() {
void shouldFalseOnNoMatchingRole() {
var userRole = LoremIpsum.getInstance().getWords(1);
var rolesToCheck = Set.of(LoremIpsum.getInstance().getWords(1), LoremIpsum.getInstance().getWords(1));
List<GrantedAuthority> authorities = List.of(
new SimpleGrantedAuthority(CurrentUserHelper.ROLE_PREFIX + "OTHER"));
new SimpleGrantedAuthority(CurrentUserHelper.ROLE_PREFIX + userRole));
boolean containsRole = CurrentUserHelper.containsRole(authorities, UserRole.ADMIN_ADMIN);
boolean containsRole = CurrentUserHelper.containsAnyRole(authorities, rolesToCheck);
assertThat(containsRole).isFalse();
}
@Test
void shouldContainRole() {
Collection<? extends GrantedAuthority> authorities = List.of(
new SimpleGrantedAuthority(CurrentUserHelper.ROLE_PREFIX + UserRole.ADMIN_ADMIN));
void shouldReturnTrueOnMatchingRole() {
var userRole = LoremIpsum.getInstance().getWords(1);
var rolesToCheck = Set.of(LoremIpsum.getInstance().getWords(1), userRole);
List<GrantedAuthority> authorities = List.of(
new SimpleGrantedAuthority(CurrentUserHelper.ROLE_PREFIX + userRole));
boolean containsRole = CurrentUserHelper.containsRole(authorities, UserRole.ADMIN_ADMIN);
boolean containsRole = CurrentUserHelper.containsAnyRole(authorities, rolesToCheck);
assertThat(containsRole).isTrue();
}
......@@ -166,13 +208,13 @@ class CurrentUserHelperTest {
@Nested
class TestGetAuthentication {
@Mock
private final SecurityContext mockSecurityContext = Mockito.mock(SecurityContext.class);
private final SecurityContext mockSecurityContext = mock(SecurityContext.class);
@Test
void shouldThrowIfNoAuthenticatedUser() {
Mockito.when(mockSecurityContext.getAuthentication()).thenReturn(null);
when(mockSecurityContext.getAuthentication()).thenReturn(null);
try (MockedStatic<SecurityContextHolder> contextHolder = Mockito.mockStatic(SecurityContextHolder.class)) {
try (MockedStatic<SecurityContextHolder> contextHolder = mockStatic(SecurityContextHolder.class)) {
contextHolder.when(SecurityContextHolder::getContext).thenReturn(mockSecurityContext);
assertThatIllegalStateException()
......@@ -183,10 +225,10 @@ class CurrentUserHelperTest {
@Test
void shouldPassAuthentication() {
Authentication mockAuthentication = Mockito.mock(Authentication.class);
Mockito.when(mockSecurityContext.getAuthentication()).thenReturn(mockAuthentication);
Authentication mockAuthentication = mock(Authentication.class);
when(mockSecurityContext.getAuthentication()).thenReturn(mockAuthentication);
try (MockedStatic<SecurityContextHolder> contextHolder = Mockito.mockStatic(SecurityContextHolder.class)) {
try (MockedStatic<SecurityContextHolder> contextHolder = mockStatic(SecurityContextHolder.class)) {
contextHolder.when(SecurityContextHolder::getContext).thenReturn(mockSecurityContext);
Authentication authentication = CurrentUserHelper.getAuthentication();
......
......@@ -23,14 +23,16 @@
*/
package de.ozgcloud.admin.common.user;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import static org.assertj.core.api.Assertions.assertThat;
class CurrentUserServiceTest {
private final CurrentUserService currentUserService = new CurrentUserService();
......@@ -39,12 +41,10 @@ class CurrentUserServiceTest {
@Nested
class TestHasRole {
@ParameterizedTest
@ValueSource(booleans = {false, true})
@ValueSource(booleans = { false, true })
void shouldReturnValue(boolean hasRoleValue) {
try (MockedStatic<CurrentUserHelper> mockUserHelper = Mockito.mockStatic(
CurrentUserHelper.class)
){
mockUserHelper.when(() -> CurrentUserHelper.hasRole(Mockito.anyString()))
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class)) {
mockUserHelper.when(() -> CurrentUserHelper.hasRole(anyString()))
.thenReturn(hasRoleValue);
boolean hasRole = currentUserService.hasRole(UserRole.ADMIN_ADMIN);
......@@ -54,4 +54,29 @@ class CurrentUserServiceTest {
}
}
}
@Nested
class TestHasConfigurationPermission {
@Test
void shouldCallCurrentUserHelper() {
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class)) {
currentUserService.hasConfigurationPermission();
mockUserHelper.verify(() -> CurrentUserHelper.hasAnyRole(UserRole.CONFIGURATION_ROLES));
}
}
@ParameterizedTest
@ValueSource(booleans = { false, true })
void shouldReturnValue(boolean hasConfigurationPermission) {
try (MockedStatic<CurrentUserHelper> mockUserHelper = mockStatic(CurrentUserHelper.class)) {
mockUserHelper.when(() -> CurrentUserHelper.hasAnyRole(any())).thenReturn(hasConfigurationPermission);
var result = currentUserService.hasConfigurationPermission();
assertThat(result).isEqualTo(hasConfigurationPermission);
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment