Merge branch 'RED-8491' into 'main'

RED-8491: Hide all KNECON_* roles for any possible access in all endpoints

See merge request fforesight/tenant-user-management-service!105
This commit is contained in:
Maverick Studer 2024-06-04 09:05:42 +02:00
commit ed86367ab8
7 changed files with 354 additions and 51 deletions

View File

@ -1,6 +1,5 @@
package com.knecon.fforesight.tenantusermanagement.controller.external;
import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.DELETE_TENANT;
import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.READ_ALL_USERS;
import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.READ_USERS;
import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.UPDATE_MY_PROFILE;
@ -26,6 +25,7 @@ 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.model.User;
import com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles;
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
import com.knecon.fforesight.tenantusermanagement.service.UserService;
@ -41,9 +41,6 @@ public class UserController implements UserResource, PublicResource {
private final UserService userService;
private final TenantUserManagementProperties tenantUserManagementProperties;
private static final String KNECON_ADMIN_ROLE = "KNECON_ADMIN";
private static final String KNECON_SUPPORT_ROLE = "KNECON_SUPPORT";
@Override
@PreAuthorize("hasAuthority('" + READ_USERS + "')")
@ -76,7 +73,7 @@ public class UserController implements UserResource, PublicResource {
.filter(user -> {
Set<String> filteredRoles = user.getRoles()
.stream()
.filter(role -> !role.equals(KNECON_ADMIN_ROLE) && !role.equals(KNECON_SUPPORT_ROLE))
.filter(ApplicationRoles::isNoKneconRole)
.collect(Collectors.toSet());
if (filteredRoles.isEmpty()) {
@ -142,7 +139,7 @@ public class UserController implements UserResource, PublicResource {
Set<String> filteredRoles = user.getRoles()
.stream()
.filter(role -> !role.equals(KNECON_ADMIN_ROLE) && !role.equals(KNECON_SUPPORT_ROLE))
.filter(ApplicationRoles::isNoKneconRole)
.collect(Collectors.toSet());
if (filteredRoles.isEmpty()) {

View File

@ -0,0 +1,22 @@
package com.knecon.fforesight.tenantusermanagement.permissions;
import java.util.Set;
public final class ApplicationRoles {
public static final String KNECON_ADMIN_ROLE = "KNECON_ADMIN";
public static final String KNECON_SUPPORT_ROLE = "KNECON_SUPPORT";
private static final Set<String> KNECON_ROLES = Set.of(KNECON_ADMIN_ROLE, KNECON_SUPPORT_ROLE);
public static boolean isNoKneconRole(String role) {
return !KNECON_ROLES.contains(role);
}
public static boolean isKneconRole(String role) {
return KNECON_ROLES.contains(role);
}
}

View File

@ -39,6 +39,7 @@ 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.model.User;
import com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles;
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
import io.micrometer.common.util.StringUtils;
@ -78,7 +79,7 @@ public class UserService {
String username = StringUtils.isEmpty(user.getUsername()) ? user.getEmail() : user.getUsername();
if (!this.getTenantUsersResource().search(username, true).isEmpty() || !this.getTenantUsersResource().searchByEmail(user.getEmail(), true).isEmpty()) {
throw new ResponseStatusException(HttpStatus.CONFLICT, "User with this username or email address already exists");
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Requested username or email address not available");
}
if (!EmailValidator.getInstance().isValid(user.getEmail())) {
@ -165,9 +166,13 @@ public class UserService {
var currentUserRoles = this.getUserRoles(KeycloakSecurity.getUserId());
var userWithNewRoles = setRoles(userId, roles, currentUserRoles);
if (!userId.equalsIgnoreCase(KeycloakSecurity.getUserId()) && roles.stream()
.anyMatch(ApplicationRoles::isKneconRole) && currentUserRoles.stream()
.noneMatch(ApplicationRoles::isKneconRole)) {
throw new NotFoundException("User with id: " + userId + " does not exist");
}
return userWithNewRoles;
return setRoles(userId, roles, currentUserRoles);
}
@ -176,7 +181,9 @@ public class UserService {
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
newRoles.forEach(role -> {
if (!allRoles.contains(role)) {
if (!allRoles.contains(role) || ApplicationRoles.isKneconRole(role) && currentUserRoles.stream()
.noneMatch(ApplicationRoles::isKneconRole)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid role: " + role);
}
});
@ -236,7 +243,7 @@ public class UserService {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot modify some roles for this user. Insufficient rights");
}
if (userId.equals(KeycloakSecurity.getUserId()) && maxRank.equals(roleMapping.getMaxRank()) && !maxNewRolesRank.equals(maxRank)) {
if (userId.equalsIgnoreCase(KeycloakSecurity.getUserId()) && maxRank.equals(roleMapping.getMaxRank()) && !maxNewRolesRank.equals(maxRank)) {
throw new ResponseStatusException(HttpStatus.CONFLICT, "Cannot remove highest ranking role from self.");
}
}
@ -412,10 +419,12 @@ public class UserService {
return;
}
var executionValid = isExecutionRankValid(KeycloakSecurity.getUserId(), userId);
var status = validateExecution(KeycloakSecurity.getUserId(), userId);
if (!executionValid) {
if (status.equals(ValidationStatus.FORBIDDEN)) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to delete a user with higher ranking roles");
} else if (status.equals(ValidationStatus.INVALID)) {
return;
}
var userResource = getUserResource(userId);
@ -434,6 +443,11 @@ public class UserService {
var user = this.getUserResource(userId);
var userRepresentation = user.toRepresentation();
if (getRoles(userId).stream()
.anyMatch(ApplicationRoles::isKneconRole)) {
throw new NotFoundException("User with id: " + userId + " does not exist");
}
if (userRepresentation.getFederatedIdentities() != null && !userRepresentation.getFederatedIdentities().isEmpty() && !updateProfileRequest.getEmail()
.equals(userRepresentation.getEmail())) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to change the email from a federated identity");
@ -462,10 +476,14 @@ public class UserService {
public User activateProfile(String userId, boolean isActive) {
var executionValid = isExecutionRankValid(KeycloakSecurity.getUserId(), userId);
if (!userId.equalsIgnoreCase(KeycloakSecurity.getUserId())) {
var status = validateExecution(KeycloakSecurity.getUserId(), userId);
if (!executionValid) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to activate/deactivate a user with higher ranking roles");
if (status.equals(ValidationStatus.FORBIDDEN)) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to activate/deactivate a user with higher ranking roles");
} else if (status.equals(ValidationStatus.INVALID)) {
throw new NotFoundException("User with id: " + userId + " does not exist");
}
}
var user = this.getUserResource(userId);
@ -491,10 +509,14 @@ public class UserService {
public void resetPassword(String userId, ResetPasswordRequest resetPasswordRequest) {
var executionValid = isExecutionRankValid(KeycloakSecurity.getUserId(), userId);
if (!userId.equalsIgnoreCase(KeycloakSecurity.getUserId())) {
var status = validateExecution(KeycloakSecurity.getUserId(), userId);
if (!executionValid) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to reset the password of a user with higher ranking roles");
if (status.equals(ValidationStatus.FORBIDDEN)) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to reset the password of a user with higher ranking roles");
} else if (status.equals(ValidationStatus.INVALID)) {
throw new NotFoundException("User with id: " + userId + " does not exist");
}
}
try {
@ -542,13 +564,24 @@ public class UserService {
}
private boolean isExecutionRankValid(String executingUserId, String targetUserId) {
private enum ValidationStatus {
ALLOWED,
FORBIDDEN,
INVALID
}
private ValidationStatus validateExecution(String executingUserId, String targetUserId) {
var currentUserResource = getUserResource(executingUserId);
var currentRoles = getRoles(currentUserResource.toRepresentation().getId());
var userRoles = getRoles(targetUserId);
if (currentRoles.stream()
.anyMatch(ApplicationRoles::isKneconRole)) {
return ValidationStatus.INVALID;
}
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
var maxRank = currentRoles.stream()
.map(r -> roleMapping.getRole(r).getRank())
@ -559,8 +592,11 @@ public class UserService {
.max(Integer::compare)
.orElse(-1);
return targetRank <= maxRank;
if (targetRank <= maxRank) {
return ValidationStatus.ALLOWED;
} else {
return ValidationStatus.FORBIDDEN;
}
}
}

View File

@ -30,6 +30,44 @@ fforesight:
- 'fforesight-write-smtp-configuration'
- 'fforesight-read-identity-provider-config'
- 'fforesight-write-identity-provider-config'
- name: KNECON_ADMIN
set-by-default: true
rank: 1000
permissions:
- 'fforesight-read-general-configuration'
- 'fforesight-write-general-configuration'
- 'fforesight-manage-user-preferences'
- 'fforesight-read-users'
- 'fforesight-read-all-users'
- 'fforesight-write-users'
- 'fforesight-update-my-profile'
- 'fforesight-create-tenant'
- 'fforesight-get-tenants'
- 'fforesight-update-tenant'
- 'fforesight-deployment-info'
- 'fforesight-read-smtp-configuration'
- 'fforesight-write-smtp-configuration'
- 'fforesight-read-identity-provider-config'
- 'fforesight-write-identity-provider-config'
- name: KNECON_SUPPORT
set-by-default: true
rank: 1000
permissions:
- 'fforesight-read-general-configuration'
- 'fforesight-write-general-configuration'
- 'fforesight-manage-user-preferences'
- 'fforesight-read-users'
- 'fforesight-read-all-users'
- 'fforesight-write-users'
- 'fforesight-update-my-profile'
- 'fforesight-create-tenant'
- 'fforesight-get-tenants'
- 'fforesight-update-tenant'
- 'fforesight-deployment-info'
- 'fforesight-read-smtp-configuration'
- 'fforesight-write-smtp-configuration'
- 'fforesight-read-identity-provider-config'
- 'fforesight-write-identity-provider-config'
application-name: "redaction"
springdoc:
auth-server-url: http://localhost:8080

View File

@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@ -21,6 +22,8 @@ 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.model.User;
import com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles;
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
import feign.FeignException;
@ -42,33 +45,41 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
tokenService.setUser("test@fforesight.com", "secret");
var allUsers = userClient.getAllUsers(true);
var testUserFound = allUsers.stream().anyMatch(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com"));
var testUserFound = allUsers.stream()
.anyMatch(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com"));
assertThat(allUsers).isNotEmpty();
assertThat(testUserFound).isTrue();
allUsers = userClient.getApplicationSpecificUsers(true);
testUserFound = allUsers.stream().anyMatch(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com"));
testUserFound = allUsers.stream()
.anyMatch(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com"));
assertThat(allUsers).isNotEmpty();
assertThat(testUserFound).isTrue();
var testUserId = allUsers.iterator().next().getUserId();
var testUser = userClient.getUserById(testUserId);
var optionalUser = allUsers.stream().filter(user -> user.getUsername().equalsIgnoreCase("test@fforesight.com")).findFirst();
assert(optionalUser.isPresent());
var testUser = userClient.getUserById(optionalUser.get().getUserId());
assertThat(testUser).isNotNull();
testUser = userClient.updateMyProfile(UpdateMyProfileRequest.builder()
.email("test@fforesight.com")
.firstName("updateTestFirstName")
.lastName("updateTestLastName")
.build());
.email("test@fforesight.com")
.firstName("updateTestFirstName")
.lastName("updateTestLastName")
.build());
assertThat(testUser.getLastName()).isEqualTo("updateTestLastName");
assertThat(testUser.getFirstName()).isEqualTo("updateTestFirstName");
Set<String> allButKneconRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles().stream()
.filter(ApplicationRoles::isNoKneconRole)
.collect(Collectors.toSet());
CreateUserRequest createUserRequest = new CreateUserRequest();
createUserRequest.setEmail("test.new.user@knecon.com");
createUserRequest.setFirstName("Test");
createUserRequest.setLastName("New User");
createUserRequest.setUsername(createUserRequest.getEmail());
createUserRequest.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
createUserRequest.setRoles(allButKneconRoles);
var createdUser = userClient.createUser(createUserRequest);
allUsers = userClient.getAllUsers(true);
@ -84,13 +95,14 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
assertThat(createdUser.getRoles()).isEmpty();
createdUser = userClient.updateProfile(createdUser.getUserId(),
UpdateProfileRequest.builder()
.email("test.new.user@knecon.com")
.firstName("update test")
.lastName("update test")
.roles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles())
.build());
assertThat(createdUser.getRoles()).containsExactly(tenantUserManagementProperties.getKcRoleMapping().getAllRoles().toArray(new String[0]));
UpdateProfileRequest.builder()
.email("test.new.user@knecon.com")
.firstName("update test")
.lastName("update test")
.roles(allButKneconRoles)
.build());
assertThat(createdUser.getRoles()).containsExactly(allButKneconRoles
.toArray(new String[0]));
userClient.deleteUsers(List.of(createdUser.getUserId()));
@ -133,7 +145,10 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
userClient.resetPassword(createdUser2.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!2345").build());
var allUsers = userClient.getAllUsers(true);
var initialSuperUser = allUsers.stream().filter(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com")).findAny().get();
var initialSuperUser = allUsers.stream()
.filter(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com"))
.findAny()
.get();
try {
//reset password as less-super-user for super-user
userClient.resetPassword(initialSuperUser.getUserId(), ResetPasswordRequest.builder().password("ShouldNotWork@123").build());
@ -223,6 +238,7 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
TenantContext.clear();
}
@Test
@SneakyThrows
public void testActivateUserWithSameRole() {
@ -283,13 +299,16 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
public void testCreateUserWithExistingUser() {
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
Set<String> allButKneconRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles().stream()
.filter(ApplicationRoles::isNoKneconRole)
.collect(Collectors.toSet());
var createUserRequest = new CreateUserRequest();
createUserRequest.setEmail("existinguser@knecon.com");
createUserRequest.setFirstName("Existing");
createUserRequest.setLastName("User");
createUserRequest.setUsername("ExistingUser");
createUserRequest.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
createUserRequest.setRoles(allButKneconRoles);
userClient.createUser(createUserRequest);
var createUserRequest2 = new CreateUserRequest();
@ -297,46 +316,187 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
createUserRequest2.setFirstName("New");
createUserRequest2.setLastName("User");
createUserRequest2.setUsername("NewUser");
createUserRequest2.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
createUserRequest2.setRoles(allButKneconRoles);
FeignException e = assertThrows(FeignException.class, () -> userClient.createUser(createUserRequest2));
assertEquals(409, e.status());
assertEquals(400, e.status());
var createUserRequest3 = new CreateUserRequest();
createUserRequest3.setEmail("newuser@knecon.com");
createUserRequest3.setFirstName("New");
createUserRequest3.setLastName("User");
createUserRequest3.setUsername("ExistingUser");
createUserRequest3.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
createUserRequest3.setRoles(allButKneconRoles);
e = assertThrows(FeignException.class, () -> userClient.createUser(createUserRequest3));
assertEquals(409, e.status());
assertEquals(400, e.status());
var createUserRequest4 = new CreateUserRequest();
createUserRequest4.setEmail("existinguser@knecon.com");
createUserRequest4.setFirstName("New");
createUserRequest4.setLastName("User");
createUserRequest4.setUsername("ExistingUser");
createUserRequest4.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
createUserRequest4.setRoles(allButKneconRoles);
e = assertThrows(FeignException.class, () -> userClient.createUser(createUserRequest4));
assertEquals(409, e.status());
assertEquals(400, e.status());
var createUserRequest5 = new CreateUserRequest();
createUserRequest5.setEmail("anotherexistinguser@knecon.com");
createUserRequest5.setFirstName("Another existing");
createUserRequest5.setLastName("User");
createUserRequest5.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
createUserRequest5.setRoles(allButKneconRoles);
userClient.createUser(createUserRequest5);
var createUserRequest6 = new CreateUserRequest();
createUserRequest6.setEmail("anotherexistinguser@knecon.com");
createUserRequest6.setFirstName("Another new");
createUserRequest6.setLastName("User");
createUserRequest6.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
createUserRequest6.setRoles(allButKneconRoles);
e = assertThrows(FeignException.class, () -> userClient.createUser(createUserRequest6));
assertEquals(409, e.status());
assertEquals(400, e.status());
}
@Test
public void testHiddenKneconRoles() {
// set context and user
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
tokenService.setUser("admin@knecon.com", "secret");
// different role sets and subsets
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
Set<String> allButKneconRoles = allRoles.stream()
.filter(ApplicationRoles::isNoKneconRole)
.collect(Collectors.toSet());
Set<String> onlyKneconRoles = allRoles.stream()
.filter(ApplicationRoles::isKneconRole)
.collect(Collectors.toSet());
var sizeBefore = userClient.getAllUsers(true).size();
// create several users with different roles for testing
var createUserRequest = new CreateUserRequest();
createUserRequest.setEmail("allroles@knecon.com");
createUserRequest.setFirstName("All");
createUserRequest.setLastName("Roles");
createUserRequest.setUsername("AllRoles");
createUserRequest.setRoles(allRoles);
User user = userClient.createUser(createUserRequest);
var createUserRequest2 = new CreateUserRequest();
createUserRequest2.setEmail("nokneconroles@notknecon.com");
createUserRequest2.setFirstName("No Knecon");
createUserRequest2.setLastName("Roles");
createUserRequest2.setUsername("NoKneconRoles");
createUserRequest2.setRoles(allButKneconRoles);
User noKneconUser = userClient.createUser(createUserRequest2);
var createUserRequest3 = new CreateUserRequest();
createUserRequest3.setEmail("onlykneconroles@notknecon.com");
createUserRequest3.setFirstName("Only Knecon");
createUserRequest3.setLastName("Roles");
createUserRequest3.setUsername("OnlyKneconRoles");
createUserRequest3.setRoles(onlyKneconRoles);
User onlyKneconUser = userClient.createUser(createUserRequest3);
var allUsers = userClient.getAllUsers(true);
// one role is completely hidden
assertEquals(allUsers.size(), sizeBefore + 2);
// no knecon roles are visible
assertEquals(allUsers.stream().filter(u -> u.getRoles().stream().anyMatch(ApplicationRoles::isKneconRole)).count(), 0);
// we can get this user because of other roles being present
userClient.getUserById(noKneconUser.getUserId());
// but not this one as he only has knecon roles
var e = assertThrows(FeignException.class, () -> userClient.getUserById(onlyKneconUser.getUserId()));
assertEquals(404, e.status());
// switch token to the user without knecon roles
tokenService.setUser("test@fforesight.com", "secret");
// create another dummy user with only SUPER_USER
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);
// reset password for authentication
userClient.resetPassword(redUserAdmin.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
// authenticate with the newly created user
tokenService.setUser("red-user-admin@knecon.com", "Secret@secured!23");
// we should not be able to set roles of this user at all as it is not visible to us resulting in a 404
e = assertThrows(FeignException.class, () -> userClient.setRoles(user.getUserId(), onlyKneconRoles));
assertEquals(404, e.status());
// we should not be able to assign ourselves a knecon role as it is not visible to us
e = assertThrows(FeignException.class, () -> userClient.setRoles(redUserAdmin.getUserId(), allRoles));
assertEquals(400, e.status());
// authenticate as knecon admin again
tokenService.setUser("admin@knecon.com", "secret");
// this should be possible because we now have knecon roles
userClient.setRoles(onlyKneconUser.getUserId(), allRoles);
assertEquals(userClient.getUserById(onlyKneconUser.getUserId()).getRoles().size(), 2);
// and this as well
userClient.setRoles(user.getUserId(), allRoles);
// we can also poll the user
userClient.getUserById(user.getUserId());
// back to having no rights
tokenService.setUser("red-user-admin@knecon.com", "Secret@secured!23");
// we can not call update profile
e = assertThrows(FeignException.class, () -> userClient.updateProfile(user.getUserId(), new UpdateProfileRequest()));
assertEquals(404, e.status());
// or reset password as it is forbidden (higher rights)
e = assertThrows(FeignException.class, () -> userClient.resetPassword(user.getUserId(), new ResetPasswordRequest()));
assertEquals(403, e.status());
// now as a knecon admin again
tokenService.setUser("admin@knecon.com", "secret");
// we can also not see another knecon account and change their password
e = assertThrows(FeignException.class, () -> userClient.resetPassword(user.getUserId(), new ResetPasswordRequest()));
assertEquals(404, e.status());
// or activate the profile
e = assertThrows(FeignException.class, () -> userClient.activateProfile(user.getUserId(), true));
assertEquals(404, e.status());
// we create a new user with all roles
var createUserRequest4 = new CreateUserRequest();
createUserRequest4.setEmail("allroles2@knecon.com");
createUserRequest4.setFirstName("All");
createUserRequest4.setLastName("Roles2");
createUserRequest4.setUsername("AllRoles2");
createUserRequest4.setRoles(allRoles);
User user4 = userClient.createUser(createUserRequest4);
// we attempt to delete it
userClient.deleteUser(user4.getUserId());
// and again using the bulk call
userClient.deleteUsers(List.of(user4.getUserId()));
// user should still be present despite deletes as it as a knecon user
assertEquals(allUsers.size(), sizeBefore + 2);
// and should not have changed
var user5 = userClient.getUserById(user4.getUserId());
assertEquals(user4, user5);
}

View File

@ -20,6 +20,7 @@ import com.knecon.fforesight.tenantusermanagement.api.internal.InternalTenantsRe
import com.knecon.fforesight.tenantusermanagement.model.SearchConnectionRequest;
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
import com.knecon.fforesight.tenantusermanagement.model.TenantUser;
import com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles;
import com.knecon.fforesight.tenantusermanagement.testcontainers.MongoDBTestContainer;
import com.knecon.fforesight.tenantusermanagement.testcontainers.SpringPostgreSQLTestContainer;
@ -57,7 +58,18 @@ public class TestTenantService {
.tenantId(testTenantId)
.displayName(testTenantId)
.guid(UUID.randomUUID().toString())
.defaultUsers(List.of(TenantUser.builder().roles(Set.of("SUPER_USER")).username("test@fforesight.com").password("secret").email("test@fforesight.com").build()))
.defaultUsers(List.of(TenantUser.builder()
.roles(Set.of("SUPER_USER"))
.username("test@fforesight.com")
.password("secret")
.email("test@fforesight.com")
.build(),
TenantUser.builder()
.roles(Set.of(ApplicationRoles.KNECON_ADMIN_ROLE, ApplicationRoles.KNECON_SUPPORT_ROLE))
.username("admin@knecon.com")
.password("secret")
.email("admin@knecon.com")
.build()))
.databaseConnection(DatabaseConnection.builder()
.driver("postgresql")
.host(SpringPostgreSQLTestContainer.getInstance().getHost())

View File

@ -144,6 +144,44 @@ fforesight:
- 'fforesight-write-smtp-configuration'
- 'fforesight-read-identity-provider-config'
- 'fforesight-write-identity-provider-config'
- name: KNECON_ADMIN
set-by-default: true
rank: 1000
permissions:
- 'fforesight-read-general-configuration'
- 'fforesight-write-general-configuration'
- 'fforesight-manage-user-preferences'
- 'fforesight-read-users'
- 'fforesight-read-all-users'
- 'fforesight-write-users'
- 'fforesight-update-my-profile'
- 'fforesight-create-tenant'
- 'fforesight-get-tenants'
- 'fforesight-update-tenant'
- 'fforesight-deployment-info'
- 'fforesight-read-smtp-configuration'
- 'fforesight-write-smtp-configuration'
- 'fforesight-read-identity-provider-config'
- 'fforesight-write-identity-provider-config'
- name: KNECON_SUPPORT
set-by-default: true
rank: 1000
permissions:
- 'fforesight-read-general-configuration'
- 'fforesight-write-general-configuration'
- 'fforesight-manage-user-preferences'
- 'fforesight-read-users'
- 'fforesight-read-all-users'
- 'fforesight-write-users'
- 'fforesight-update-my-profile'
- 'fforesight-create-tenant'
- 'fforesight-get-tenants'
- 'fforesight-update-tenant'
- 'fforesight-deployment-info'
- 'fforesight-read-smtp-configuration'
- 'fforesight-write-smtp-configuration'
- 'fforesight-read-identity-provider-config'
- 'fforesight-write-identity-provider-config'
access-token-life-span: 86400
application-name: tenant-user-management
application-client-id: tenant-user-management