Merge branch 'RED-3387' into 'main'
RED-3387: No Welcome Email for SSO User See merge request fforesight/tenant-user-management-service!101
This commit is contained in:
commit
1c7698d2de
@ -25,4 +25,7 @@ public class CreateUserRequest {
|
||||
@Schema(description = "Roles to assign to user.")
|
||||
private Set<String> roles = new HashSet<>();
|
||||
|
||||
@Schema(description = "Whether a set password mail should be sent")
|
||||
private boolean sendSetPasswordMail;
|
||||
|
||||
}
|
||||
|
||||
@ -67,6 +67,9 @@ public class GeneralConfigurationService {
|
||||
|
||||
var realmRepresentation = realm.toRepresentation();
|
||||
realmRepresentation.setResetPasswordAllowed(generalConfigurationModel.isForgotPasswordFunctionEnabled());
|
||||
|
||||
realmRepresentation.getAttributes().put("actionTokenGeneratedByUserLifespan.idp-verify-account-via-email", Integer.toString(86400));
|
||||
|
||||
if (!StringUtils.isEmpty(generalConfigurationModel.getAuxiliaryName())) {
|
||||
setDisplayName(realmRepresentation, tenantUserManagementProperties.getApplicationName() + " (" + generalConfigurationModel.getAuxiliaryName() + ")");
|
||||
} else {
|
||||
|
||||
@ -8,11 +8,6 @@ import java.util.TreeSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.ws.rs.ClientErrorException;
|
||||
import jakarta.ws.rs.NotAuthorizedException;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import org.apache.commons.validator.routines.EmailValidator;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
@ -23,7 +18,6 @@ import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
@ -48,6 +42,10 @@ import com.knecon.fforesight.tenantusermanagement.model.User;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import jakarta.ws.rs.ClientErrorException;
|
||||
import jakarta.ws.rs.NotAuthorizedException;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ -112,10 +110,12 @@ public class UserService {
|
||||
|
||||
var createdUser = getUserByUsername(username);
|
||||
|
||||
try {
|
||||
sendResetPasswordEmail(createdUser.getUserId());
|
||||
} catch (Exception e) {
|
||||
log.debug("Activation E-mail could not be sent!", e);
|
||||
if (user.isSendSetPasswordMail()) {
|
||||
try {
|
||||
sendResetPasswordEmail(createdUser.getUserId());
|
||||
} catch (Exception e) {
|
||||
log.debug("Set Password E-mail could not be sent!", e);
|
||||
}
|
||||
}
|
||||
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.created", new UserCreatedEvent(createdUser, KeycloakSecurity.getUserId()));
|
||||
@ -132,9 +132,16 @@ public class UserService {
|
||||
public void checkRankOrderForAssigningRole(Set<String> newRoles, Set<String> currentUserRoles) {
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var maxRank = currentUserRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
var newRolesRank = newRoles.stream().map(r -> roleMapping.getRole(r).getRank()).toList();
|
||||
var maxNewRolesRank = newRolesRank.stream().max(Integer::compare).orElse(-1);
|
||||
var maxRank = currentUserRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
var newRolesRank = newRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.toList();
|
||||
var maxNewRolesRank = newRolesRank.stream()
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
|
||||
if (maxNewRolesRank > maxRank) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot assign this role to that user. Insufficient rights");
|
||||
@ -145,9 +152,7 @@ public class UserService {
|
||||
public Set<String> getUserRoles(String userId) {
|
||||
|
||||
var userResource = getUserResource(userId);
|
||||
return userResource.roles()
|
||||
.realmLevel()
|
||||
.listEffective()
|
||||
return userResource.roles().realmLevel().listEffective()
|
||||
.stream()
|
||||
.map(RoleRepresentation::getName)
|
||||
.filter(r -> tenantUserManagementProperties.getKcRoleMapping().isValidRole(r))
|
||||
@ -177,12 +182,19 @@ public class UserService {
|
||||
});
|
||||
|
||||
var userResource = getUserResource(userId);
|
||||
var userRoles = userResource.roles().realmLevel().listEffective().stream().map(RoleRepresentation::getName).collect(Collectors.toSet());
|
||||
var userRoles = userResource.roles().realmLevel().listEffective()
|
||||
.stream()
|
||||
.map(RoleRepresentation::getName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
validateSufficientRoles(userId, userRoles, newRoles, currentUserRoles);
|
||||
|
||||
var currentRolesAsRoleRepresentation = allRoles.stream().map(this::getRoleRepresentation).collect(Collectors.toList());
|
||||
var newMappedRoles = newRoles.stream().map(this::getRoleRepresentation).collect(Collectors.toList());
|
||||
var currentRolesAsRoleRepresentation = allRoles.stream()
|
||||
.map(this::getRoleRepresentation)
|
||||
.collect(Collectors.toList());
|
||||
var newMappedRoles = newRoles.stream()
|
||||
.map(this::getRoleRepresentation)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
userResource.roles().realmLevel().remove(currentRolesAsRoleRepresentation);
|
||||
userResource.roles().realmLevel().add(newMappedRoles);
|
||||
@ -198,9 +210,16 @@ public class UserService {
|
||||
public void validateSufficientRoles(String userId, Set<String> userRoles, Set<String> newRoles, Set<String> currentUserRoles) {
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var maxRank = currentUserRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
var newRolesRank = newRoles.stream().map(r -> roleMapping.getRole(r).getRank()).toList();
|
||||
var maxNewRolesRank = newRolesRank.stream().max(Integer::compare).orElse(-1);
|
||||
var maxRank = currentUserRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
var newRolesRank = newRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.toList();
|
||||
var maxNewRolesRank = newRolesRank.stream()
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
|
||||
var untouchableRoles = userRoles.stream()
|
||||
.filter(roleMapping::isValidRole)
|
||||
@ -225,7 +244,10 @@ public class UserService {
|
||||
|
||||
public Optional<User> getUserById(String userId) {
|
||||
|
||||
return userListingService.getAllUsers(TenantContext.getTenantId()).stream().filter(u -> u.getUserId().equalsIgnoreCase(userId)).findAny();
|
||||
return userListingService.getAllUsers(TenantContext.getTenantId())
|
||||
.stream()
|
||||
.filter(u -> u.getUserId().equalsIgnoreCase(userId))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
|
||||
@ -272,7 +294,8 @@ public class UserService {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "No id provided.");
|
||||
}
|
||||
try {
|
||||
return this.getTenantUsersResource().get(userId);
|
||||
return this.getTenantUsersResource()
|
||||
.get(userId);
|
||||
} catch (NotFoundException e) {
|
||||
throw new NotFoundException("User with id: " + userId + " does not exist", e);
|
||||
}
|
||||
@ -294,10 +317,10 @@ public class UserService {
|
||||
.clientId(tenantUserManagementProperties.getApplicationClientId())
|
||||
.grantType(OAuth2Constants.PASSWORD)
|
||||
.resteasyClient(new ResteasyClientBuilderImpl().connectionTTL(2, TimeUnit.SECONDS)
|
||||
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
.connectionPoolSize(tenantUserManagementProperties.getConnectionPoolSize())
|
||||
.disableTrustManager()
|
||||
.build())
|
||||
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
.connectionPoolSize(tenantUserManagementProperties.getConnectionPoolSize())
|
||||
.disableTrustManager()
|
||||
.build())
|
||||
.build();
|
||||
|
||||
try {
|
||||
@ -364,13 +387,17 @@ public class UserService {
|
||||
|
||||
private Set<String> getRoles(String id) {
|
||||
|
||||
List<RoleRepresentation> realmMappings = this.getTenantUsersResource().get(id).roles().getAll().getRealmMappings();
|
||||
List<RoleRepresentation> realmMappings = this.getTenantUsersResource()
|
||||
.get(id).roles().getAll().getRealmMappings();
|
||||
if (realmMappings == null) {
|
||||
log.warn("User with id=" + id + " contains null role mappings.");
|
||||
return new TreeSet<>();
|
||||
}
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
return realmMappings.stream().map(RoleRepresentation::getName).filter(allRoles::contains).collect(Collectors.toSet());
|
||||
return realmMappings.stream()
|
||||
.map(RoleRepresentation::getName)
|
||||
.filter(allRoles::contains)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
@ -457,7 +484,8 @@ public class UserService {
|
||||
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.statusChanged", (new UserStatusToggleEvent(toggledUser, KeycloakSecurity.getUserId())));
|
||||
|
||||
return convert(this.getTenantUsersResource().get(userId).toRepresentation());
|
||||
return convert(this.getTenantUsersResource()
|
||||
.get(userId).toRepresentation());
|
||||
}
|
||||
|
||||
|
||||
@ -474,7 +502,8 @@ public class UserService {
|
||||
request.setType(CredentialRepresentation.PASSWORD);
|
||||
request.setTemporary(resetPasswordRequest.isTemporary());
|
||||
request.setValue(resetPasswordRequest.getPassword());
|
||||
realmService.realm(TenantContext.getTenantId()).users().get(userId).resetPassword(request);
|
||||
realmService.realm(TenantContext.getTenantId()).users()
|
||||
.get(userId).resetPassword(request);
|
||||
log.info("User {} resetted password for user {}", KeycloakSecurity.getUserId(), userId);
|
||||
} catch (Exception e) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Could not reset password. It does not match the password policy.", e);
|
||||
@ -492,7 +521,8 @@ public class UserService {
|
||||
|
||||
RoleRepresentation realmRole;
|
||||
try {
|
||||
realmRole = realmService.realm(TenantContext.getTenantId()).roles().get(role).toRepresentation();
|
||||
realmRole = realmService.realm(TenantContext.getTenantId()).roles()
|
||||
.get(role).toRepresentation();
|
||||
} catch (NotFoundException e) {
|
||||
log.warn("The realm role {} is not found.", role);
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "The realm role " + role + " is not found.", e);
|
||||
@ -504,7 +534,8 @@ public class UserService {
|
||||
private void sendResetPasswordEmail(String userId) {
|
||||
|
||||
try {
|
||||
this.getTenantUsersResource().get(userId).executeActionsEmail(Collections.singletonList("UPDATE_PASSWORD"), 86400);
|
||||
this.getTenantUsersResource()
|
||||
.get(userId).executeActionsEmail(Collections.singletonList("UPDATE_PASSWORD"), 86400);
|
||||
} catch (Exception e) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to send email.", e);
|
||||
}
|
||||
@ -519,8 +550,14 @@ public class UserService {
|
||||
var userRoles = getRoles(targetUserId);
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var maxRank = currentRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
var targetRank = userRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
var maxRank = currentRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
var targetRank = userRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
|
||||
return targetRank <= maxRank;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user