Red-6659 - Don't allow users with lower rank roles to activate/deactivate users with higher rank roles

This commit is contained in:
Andrei Isvoran 2024-02-06 11:56:45 +01:00 committed by Ali Oezyetimoglu
parent 1272d91e74
commit 5c0679f1fc
3 changed files with 136 additions and 6 deletions

View File

@ -120,7 +120,8 @@ public interface UserResource {
@ResponseBody
@Operation(summary = "Activate/deactivate a user profile", description = "None")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Failed to activate/deactivate profile")})
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Failed to activate/deactivate profile"),
@ApiResponse(responseCode = "403", description = "Cannot activate/deactivate users with higher rank roles")})
@PostMapping(value = ACTIVATE_USER_PROFILE_PATH + USER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
User activateProfile(@PathVariable(USER_ID) String userId, @RequestParam(IS_ACTIVE_PARAM) boolean isActive);

View File

@ -438,6 +438,12 @@ public class UserService {
public User activateProfile(String userId, boolean isActive) {
var executionValid = isExecutionRankValid(KeycloakSecurity.getUserId(), userId);
if (!executionValid) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to activate/deactivate a user with higher ranking roles");
}
var user = this.getUserResource(userId);
var userRepresentation = user.toRepresentation();
@ -445,6 +451,7 @@ public class UserService {
user.update(userRepresentation);
var currentRoles = getRoles(userId);
if (isActive && currentRoles.isEmpty()) { // add RED_USER role
setRoles(userId, tenantUserManagementProperties.getKcRoleMapping().getDefaultRoles());
}

View File

@ -3,27 +3,29 @@ package com.knecon.fforesight.tenantusermanagement.tests;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.SneakyThrows;
import feign.FeignException;
import com.knecon.fforesight.tenantcommons.TenantContext;
import com.knecon.fforesight.tenantusermanagement.AbstractTenantUserManagementIntegrationTest;
import com.knecon.fforesight.tenantusermanagement.feigntestclients.external.UserClient;
import com.knecon.fforesight.tenantcommons.TenantContext;
import com.knecon.fforesight.tenantusermanagement.model.CreateUserRequest;
import com.knecon.fforesight.tenantusermanagement.model.ResetPasswordRequest;
import com.knecon.fforesight.tenantusermanagement.model.UpdateMyProfileRequest;
import com.knecon.fforesight.tenantusermanagement.model.UpdateProfileRequest;
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
import feign.FeignException;
import lombok.SneakyThrows;
public class UserTest extends AbstractTenantUserManagementIntegrationTest {
@Autowired
@ -37,6 +39,7 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
public void testUsers() {
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
tokenService.setUser("test@fforesight.com", "secret");
var allUsers = userClient.getAllUsers(true);
var testUserFound = allUsers.stream().anyMatch(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com"));
@ -93,6 +96,8 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
allUsers = userClient.getAllUsers(true);
assertThat(allUsers).hasSize(1);
TenantContext.clear();
}
@ -138,6 +143,123 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
assertThat(e.status()).isEqualTo(403);
}
TenantContext.clear();
}
@Test
@SneakyThrows
public void testActivateUserWithLowerRole() {
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
tokenService.setUser("test@fforesight.com", "secret");
var redAdminUserRequest = new CreateUserRequest();
redAdminUserRequest.setEmail("red-admin@knecon.com");
redAdminUserRequest.setUsername(redAdminUserRequest.getEmail());
redAdminUserRequest.setRoles(Set.of("SUPER_USER"));
var redAdmin = userClient.createUser(redAdminUserRequest);
var redUserAdminUserRequest = new CreateUserRequest();
redUserAdminUserRequest.setEmail("red-user-admin@knecon.com");
redUserAdminUserRequest.setUsername(redUserAdminUserRequest.getEmail());
redUserAdminUserRequest.setRoles(Set.of("LESS_SUPER_USER"));
var redUserAdmin = userClient.createUser(redUserAdminUserRequest);
userClient.resetPassword(redAdmin.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
userClient.resetPassword(redUserAdmin.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
// authenticate as red-admin
tokenService.setUser("red-admin@knecon.com", "Secret@secured!23");
// activate red-user-admin should work since the user has a lower rank
var user = userClient.activateProfile(redUserAdmin.getUserId(), true);
assertTrue(user.isActive());
// deactivate red-user-admin should work since the user has a lower rank
user = userClient.activateProfile(redUserAdmin.getUserId(), false);
assertFalse(user.isActive());
tokenService.setUser("test@fforesight.com", "secret");
userClient.deleteUser(redUserAdmin.getUserId());
userClient.deleteUser(redAdmin.getUserId());
TenantContext.clear();
}
@Test
@SneakyThrows
public void testActivateUserWithHigherRole() {
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
tokenService.setUser("test@fforesight.com", "secret");
var redAdminUserRequest = new CreateUserRequest();
redAdminUserRequest.setEmail("red-admin@knecon.com");
redAdminUserRequest.setUsername(redAdminUserRequest.getEmail());
redAdminUserRequest.setRoles(Set.of("SUPER_USER"));
var redAdmin = userClient.createUser(redAdminUserRequest);
var redUserAdminUserRequest = new CreateUserRequest();
redUserAdminUserRequest.setEmail("red-user-admin@knecon.com");
redUserAdminUserRequest.setUsername(redUserAdminUserRequest.getEmail());
redUserAdminUserRequest.setRoles(Set.of("LESS_SUPER_USER"));
var redUserAdmin = userClient.createUser(redUserAdminUserRequest);
userClient.resetPassword(redAdmin.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
userClient.resetPassword(redUserAdmin.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
// authenticate as red-user-admin
tokenService.setUser("red-user-admin@knecon.com", "Secret@secured!23");
// activate red-admin should not work since the user has a higher rank
FeignException feignException = assertThrows(FeignException.class, () -> userClient.activateProfile(redAdmin.getUserId(), true));
assertEquals(feignException.status(), 403);
assertTrue(feignException.getMessage().contains("It is not allowed to activate/deactivate a user with higher ranking role"));
tokenService.setUser("test@fforesight.com", "secret");
userClient.deleteUser(redUserAdmin.getUserId());
userClient.deleteUser(redAdmin.getUserId());
TenantContext.clear();
}
@Test
@SneakyThrows
public void testActivateUserWithSameRole() {
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
tokenService.setUser("test@fforesight.com", "secret");
var redAdminUserRequest = new CreateUserRequest();
redAdminUserRequest.setEmail("red-admin@knecon.com");
redAdminUserRequest.setUsername(redAdminUserRequest.getEmail());
redAdminUserRequest.setRoles(Set.of("SUPER_USER"));
var redAdmin = userClient.createUser(redAdminUserRequest);
var redUserAdminUserRequest = new CreateUserRequest();
redUserAdminUserRequest.setEmail("red-user-admin@knecon.com");
redUserAdminUserRequest.setUsername(redUserAdminUserRequest.getEmail());
redUserAdminUserRequest.setRoles(Set.of("SUPER_USER"));
var redUserAdmin = userClient.createUser(redUserAdminUserRequest);
userClient.resetPassword(redAdmin.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
userClient.resetPassword(redUserAdmin.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
// authenticate as red-user-admin
tokenService.setUser("red-admin@knecon.com", "Secret@secured!23");
// activate red-user-admin should work since the user has the same rank
var user = userClient.activateProfile(redUserAdmin.getUserId(), true);
assertTrue(user.isActive());
// deactivate red-user-admin should work since the user has the same rank
user = userClient.activateProfile(redUserAdmin.getUserId(), false);
assertFalse(user.isActive());
tokenService.setUser("test@fforesight.com", "secret");
userClient.deleteUser(redUserAdmin.getUserId());
userClient.deleteUser(redAdmin.getUserId());
TenantContext.clear();
}