From b9d18b1d7581a984a4a3905451b0bb9cf6dbb100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Voz=C3=A1r?= Date: Tue, 26 Aug 2025 18:45:44 +0200 Subject: [PATCH 1/8] NAE-2173 - implementacia fukcionality zmeny hesla pre pouzivatela --- nae-object-library/pom.xml | 2 +- .../objects/auth/domain/AbstractUser.java | 10 ++++++ .../engine/objects/auth/domain/User.java | 6 ---- .../engine/auth/service/UserServiceImpl.java | 32 +++++++++++++++++++ .../engine/auth/service/UserService.java | 10 ++++++ .../engine/auth/web/responsebodies/User.java | 11 +++++++ 6 files changed, 64 insertions(+), 7 deletions(-) diff --git a/nae-object-library/pom.xml b/nae-object-library/pom.xml index 0b0d1d5449..c694c6d229 100644 --- a/nae-object-library/pom.xml +++ b/nae-object-library/pom.xml @@ -7,7 +7,7 @@ com.netgrif application-engine-parent - 7.0.0-SNAPSHOT + 7.0.0-RC6 nae-object-library diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java index 99094418b5..9f3ef35e28 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java @@ -8,6 +8,9 @@ import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; +import java.util.HashMap; +import java.util.Map; + /** * Abstract base class for user entities in the system. @@ -53,6 +56,11 @@ public abstract class AbstractUser extends AbstractActor { */ protected String avatar; + /** + * Map containing user's credentials with credential type as key + */ + protected Map> credentials = new HashMap<>(); + /** * Constructs a new user with Object ID. * @@ -73,6 +81,7 @@ public AbstractUser(ObjectId id, String realmId, String username, String firstNa this.lastName = lastName; this.email = email; this.avatar = avatar; + this.credentials = new HashMap<>(); } /** @@ -95,6 +104,7 @@ public AbstractUser(String id, String realmId, String username, String firstName this.lastName = lastName; this.email = email; this.avatar = avatar; + this.credentials = new HashMap<>(); } /** diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java index 6c49d9cef4..be5d27c448 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java @@ -1,8 +1,6 @@ package com.netgrif.application.engine.objects.auth.domain; import com.netgrif.application.engine.objects.auth.domain.enums.UserState; -import com.netgrif.application.engine.objects.annotations.Indexed; -import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import com.netgrif.application.engine.objects.utils.DateUtils; import com.querydsl.core.annotations.QueryEntity; import lombok.AllArgsConstructor; @@ -42,9 +40,6 @@ public class User extends AbstractUser implements Serializable { /** Timestamp of the last modification to the user */ private LocalDateTime modifiedAt = LocalDateTime.now(); - /** Map containing user's credentials with credential type as key */ - private Map> credentials = new HashMap<>(); - /** * Default constructor initializing a new User with a generated ObjectId * and empty maps for attributes and credentials @@ -52,7 +47,6 @@ public class User extends AbstractUser implements Serializable { public User() { this.id = new ObjectId(); this.attributes = new HashMap<>(); - this.credentials = new HashMap<>(); } /** diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java index 1fa89a13d2..eddcd6f3a1 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java @@ -260,6 +260,19 @@ public List getUserGroups(AbstractActor actor) { return groupService.findAllByIds(actor.getGroupIds(), Pageable.unpaged()).stream().toList(); } + @Override + public AbstractUser changePassword(AbstractUser user, String newPassword, String oldPassword) { + canUpdatePassword(user, newPassword); + + if (!verifyPasswords(user, oldPassword)) { + log.error("Confirmation password does not equal"); + } + + log.trace("Setting password for user [{}]", user.getUsername()); + user.setPassword(passwordEncoder.encode(newPassword)); + return saveUser(user); + } + @Override public void addDefaultAuthorities(AbstractUser user) { log.trace("Assigning default authorities to user [{}]", user.getUsername()); @@ -626,4 +639,23 @@ private void resolveRelatedProcessRoles(AbstractUser user) { user.getAuthoritySet().addAll(getUserGroups(user).stream().map(Group::getAuthoritySet).flatMap(Set::stream).collect(Collectors.toSet())); } + private boolean verifyPasswords(AbstractUser user, String password) { + if (password == null) { + throw new IllegalArgumentException("confirmation password is not set"); + } + + log.trace("Verifying password for user [{}]", user.getUsername()); + String hashedPassword = passwordEncoder.encode(password); + return Objects.equals(user.getPassword(), hashedPassword); + } + + protected void canUpdatePassword(AbstractUser user, String password) { + if (!user.isCredentialEnabled("password")) { + throw new RuntimeException("Password does not exists or authorization is not enabled"); + } + + if (password == null) { + throw new IllegalArgumentException("Password is not set"); + } + } } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index c9b6e1e329..201b798e9c 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -398,4 +398,14 @@ Page searchAllCoMembers(String query, Collection getUserGroups(AbstractActor actor); + + /** + * Resets password for user. + * + * @param user user + * @param newPassword new password + * @param oldPassword old password + * @return the updated user + */ + AbstractUser changePassword(AbstractUser user, String newPassword, String oldPassword); } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java index fef0c959fc..5462ee1403 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java @@ -4,12 +4,14 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Attribute; import com.netgrif.application.engine.objects.auth.domain.Authority; +import com.netgrif.application.engine.objects.auth.domain.Credential; import com.netgrif.application.engine.objects.auth.domain.enums.UserState; import lombok.Data; import java.time.LocalDateTime; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; @Data public class User { @@ -34,6 +36,14 @@ public class User { protected UserState state; public User(AbstractUser user) { + Attribute> enabledCredentialsAttribute = new Attribute<>(); + enabledCredentialsAttribute.setValue(user.getCredentials() + .values().stream() + .filter(Credential::isEnabled) + .map(Credential::getType) + .collect(Collectors.toSet())); + enabledCredentialsAttribute.setRequired(true); + id = user.getStringId(); username = user.getUsername(); realmId = user.getRealmId(); @@ -43,6 +53,7 @@ public User(AbstractUser user) { lastName = user.getLastName(); fullName = user.getName(); attributes = user.getAttributes(); + attributes.put("enabledCredentials", enabledCredentialsAttribute); if (user instanceof com.netgrif.application.engine.objects.auth.domain.User u) { createdAt = u.getCreatedAt(); enabled = u.isActive(); From e86404ba3bbcc0d3f7910b30a8f25479dc9a8999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Voz=C3=A1r?= Date: Tue, 26 Aug 2025 18:47:04 +0200 Subject: [PATCH 2/8] NAE-2173 - revert RC6 -> SNAPSHOT --- nae-object-library/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nae-object-library/pom.xml b/nae-object-library/pom.xml index c694c6d229..0b0d1d5449 100644 --- a/nae-object-library/pom.xml +++ b/nae-object-library/pom.xml @@ -7,7 +7,7 @@ com.netgrif application-engine-parent - 7.0.0-RC6 + 7.0.0-SNAPSHOT nae-object-library From f4e7c5a219a24b3196994b1db483ec8e4c67a6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Voz=C3=A1r?= Date: Wed, 27 Aug 2025 09:42:49 +0200 Subject: [PATCH 3/8] NAE-2173 - pull request fix, exception throwing if old password doesn't match, null checks, password verification --- .../application/engine/auth/service/UserServiceImpl.java | 5 ++--- .../application/engine/auth/web/responsebodies/User.java | 6 +++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java index eddcd6f3a1..15053c6e3d 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java @@ -265,7 +265,7 @@ public AbstractUser changePassword(AbstractUser user, String newPassword, String canUpdatePassword(user, newPassword); if (!verifyPasswords(user, oldPassword)) { - log.error("Confirmation password does not equal"); + throw new IllegalArgumentException("Old password does not match."); } log.trace("Setting password for user [{}]", user.getUsername()); @@ -645,8 +645,7 @@ private boolean verifyPasswords(AbstractUser user, String password) { } log.trace("Verifying password for user [{}]", user.getUsername()); - String hashedPassword = passwordEncoder.encode(password); - return Objects.equals(user.getPassword(), hashedPassword); + return passwordEncoder.matches(password, user.getPassword()); } protected void canUpdatePassword(AbstractUser user, String password) { diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java index 5462ee1403..e09b9232e4 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java @@ -39,8 +39,10 @@ public User(AbstractUser user) { Attribute> enabledCredentialsAttribute = new Attribute<>(); enabledCredentialsAttribute.setValue(user.getCredentials() .values().stream() + .filter(java.util.Objects::nonNull) .filter(Credential::isEnabled) .map(Credential::getType) + .filter(java.util.Objects::nonNull) .collect(Collectors.toSet())); enabledCredentialsAttribute.setRequired(true); @@ -52,7 +54,9 @@ public User(AbstractUser user) { firstName = user.getFirstName(); lastName = user.getLastName(); fullName = user.getName(); - attributes = user.getAttributes(); + attributes = user.getAttributes() != null + ? new java.util.HashMap<>(user.getAttributes()) + : new java.util.HashMap<>(); attributes.put("enabledCredentials", enabledCredentialsAttribute); if (user instanceof com.netgrif.application.engine.objects.auth.domain.User u) { createdAt = u.getCreatedAt(); From e9d26c84d21a055d7f73ea3122ce54ba7cf0956b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Voz=C3=A1r?= Date: Wed, 27 Aug 2025 09:57:04 +0200 Subject: [PATCH 4/8] NAE-2173 - Add ATTR_ENABLED_CREDENTIALS constant --- .../application/engine/auth/web/responsebodies/User.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java index e09b9232e4..4989628f1a 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java @@ -15,6 +15,7 @@ @Data public class User { + public static final String ATTR_ENABLED_CREDENTIALS = "enabledCredentials"; private String id; private String username; @@ -57,7 +58,7 @@ public User(AbstractUser user) { attributes = user.getAttributes() != null ? new java.util.HashMap<>(user.getAttributes()) : new java.util.HashMap<>(); - attributes.put("enabledCredentials", enabledCredentialsAttribute); + attributes.put(ATTR_ENABLED_CREDENTIALS, enabledCredentialsAttribute); if (user instanceof com.netgrif.application.engine.objects.auth.domain.User u) { createdAt = u.getCreatedAt(); enabled = u.isActive(); From cba755d752522cae1925ae0994eef10d9a646623 Mon Sep 17 00:00:00 2001 From: Milan Mladoniczky <6153201+tuplle@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:37:10 +0200 Subject: [PATCH 5/8] [NAE-2173] Password change - Removed credentials from `AbstractUser` and added it to `User` for better specificity. - Enhanced JavaDoc comments in `User` and `AbstractUser` for clearer documentation. - Fixed potential null pointer scenarios in credential handling within `User`. --- .../objects/auth/domain/AbstractUser.java | 20 ++--- .../engine/objects/auth/domain/User.java | 76 ++++++++++++++----- .../engine/auth/web/responsebodies/User.java | 18 +++-- 3 files changed, 72 insertions(+), 42 deletions(-) diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java index 9f3ef35e28..f9efc661c5 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractUser.java @@ -8,9 +8,6 @@ import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; -import java.util.HashMap; -import java.util.Map; - /** * Abstract base class for user entities in the system. @@ -52,15 +49,10 @@ public abstract class AbstractUser extends AbstractActor { protected String email; /** - * URL or identifier of user's avatar image + * URL or identifier of the user's avatar image */ protected String avatar; - /** - * Map containing user's credentials with credential type as key - */ - protected Map> credentials = new HashMap<>(); - /** * Constructs a new user with Object ID. * @@ -81,7 +73,6 @@ public AbstractUser(ObjectId id, String realmId, String username, String firstNa this.lastName = lastName; this.email = email; this.avatar = avatar; - this.credentials = new HashMap<>(); } /** @@ -104,7 +95,6 @@ public AbstractUser(String id, String realmId, String username, String firstName this.lastName = lastName; this.email = email; this.avatar = avatar; - this.credentials = new HashMap<>(); } /** @@ -151,7 +141,7 @@ public void activateMFA(String type, String secret) { } /** - * Activates Multi-Factor Authentication with enabled state. + * Activates Multi-Factor Authentication with the enabled state. * * @param type MFA type identifier * @param secret MFA secret key @@ -164,7 +154,7 @@ public void activateMFA(String type, String secret, boolean enabled) { * Checks if a credential is enabled. * * @param type credential type to check - * @return true if credential is enabled, false otherwise + * @return true if the credential is enabled, false otherwise */ public boolean isCredentialEnabled(String type) { return false; @@ -210,7 +200,7 @@ public Object getCredentialProperty(String type, String key) { } /** - * Returns user's first and last name concatenated. + * Returns a user's first and last name concatenated. */ @Override public String getName() { @@ -218,7 +208,7 @@ public String getName() { } /** - * Returns user's full name including middle name if present. + * Returns the user's full name including middle name if present. */ @Override public String getFullName() { diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java index be5d27c448..d9d51362b9 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java @@ -28,18 +28,31 @@ @EqualsAndHashCode(callSuper = false) public class User extends AbstractUser implements Serializable { - /** Flag indicating whether the user's email has been verified */ + /** + * Flag indicating whether the user's email has been verified + */ private boolean emailVerified; - /** Current state of the user (e.g., ACTIVE, INACTIVE) */ + /** + * Current state of the user (e.g., ACTIVE, INACTIVE) + */ private UserState state; - /** Timestamp when the user was created */ + /** + * Timestamp when the user was created + */ private LocalDateTime createdAt = LocalDateTime.now(); - /** Timestamp of the last modification to the user */ + /** + * Timestamp of the last modification to the user + */ private LocalDateTime modifiedAt = LocalDateTime.now(); + /** + * Map containing user's credentials with credential type as key + */ + protected Map> credentials; + /** * Default constructor initializing a new User with a generated ObjectId * and empty maps for attributes and credentials @@ -47,10 +60,12 @@ public class User extends AbstractUser implements Serializable { public User() { this.id = new ObjectId(); this.attributes = new HashMap<>(); + this.credentials = new HashMap<>(); } /** * Constructor creating a User with a specified ObjectId + * * @param id The ObjectId to be assigned to the user */ public User(ObjectId id) { @@ -60,6 +75,7 @@ public User(ObjectId id) { /** * Retrieves the user's authentication token from credentials + * * @return The token string if present, null otherwise */ public String getToken() { @@ -69,6 +85,7 @@ public String getToken() { /** * Sets the user's authentication token + * * @param token The token string to be stored */ public void setToken(String token) { @@ -78,6 +95,7 @@ public void setToken(String token) { /** * Retrieves the encoded password from credentials + * * @return The encoded password string if present, null otherwise */ @Override @@ -91,6 +109,7 @@ public String getPassword() { /** * Sets the user's password (should be already encoded) + * * @param password The encoded password string to store */ @Override @@ -101,6 +120,7 @@ public void setPassword(String password) { /** * Sets the expiration date for the user's token + * * @param expirationDate LocalDateTime when the token should expire */ public void setExpirationDate(LocalDateTime expirationDate) { @@ -116,6 +136,7 @@ public void setExpirationDate(LocalDateTime expirationDate) { /** * Retrieves the token expiration date + * * @return LocalDateTime of token expiration if present, null otherwise */ public LocalDateTime getExpirationDate() { @@ -132,6 +153,7 @@ public LocalDateTime getExpirationDate() { /** * Checks if a specific credential type is enabled + * * @param type The credential type to check * @return true if the credential exists and is enabled, false otherwise */ @@ -143,6 +165,7 @@ public boolean isCredentialEnabled(String type) { /** * Returns a set of enabled MFA method names + * * @return Set of strings representing enabled MFA methods */ public Set getEnabledMFAMethods() { @@ -160,6 +183,7 @@ public Set getEnabledMFAMethods() { /** * Disables a specific credential type + * * @param type The credential type to disable */ @Override @@ -171,7 +195,8 @@ public void disableCredential(String type) { /** * Activates an MFA method with the given secret (enabled by default) - * @param type The MFA type to activate + * + * @param type The MFA type to activate * @param secret The secret key for the MFA method */ @Override @@ -181,8 +206,9 @@ public void activateMFA(String type, String secret) { /** * Activates an MFA method with the given secret and enabled state - * @param type The MFA type to activate - * @param secret The secret key for the MFA method + * + * @param type The MFA type to activate + * @param secret The secret key for the MFA method * @param enabled Whether the MFA method should be enabled * @throws IllegalArgumentException if type or secret is null or empty */ @@ -200,8 +226,9 @@ public void activateMFA(String type, String secret, boolean enabled) { /** * Sets a property for a specific credential type - * @param type The credential type - * @param key The property key + * + * @param type The credential type + * @param key The property key * @param value The property value (must be Serializable) */ @Override @@ -221,8 +248,9 @@ public void setCredentialProperty(String type, String key, Object value) { /** * Retrieves a property value for a specific credential type + * * @param type The credential type - * @param key The property key + * @param key The property key * @return The property value if found, null otherwise */ @Override @@ -233,6 +261,7 @@ public Object getCredentialProperty(String type, String key) { /** * Checks if a specific credential type exists + * * @param type The credential type to check * @return true if the credential exists, false otherwise */ @@ -242,6 +271,7 @@ public boolean hasCredential(String type) { /** * Retrieves a credential by its type + * * @param type The credential type * @return The Credential object if found, null otherwise */ @@ -252,7 +282,8 @@ public Credential getCredential(String type) { /** * Sets the entire credentials map - * @param credentials The new credentials map (null creates empty map) + * + * @param credentials The new credentials map (null creates an empty map) */ public void setCredentials(Map> credentials) { this.credentials = credentials == null ? new HashMap<>() : new HashMap<>(credentials); @@ -260,9 +291,10 @@ public void setCredentials(Map> credentials) { /** * Creates and sets a new string credential - * @param type The credential type - * @param value The credential value - * @param order The credential order + * + * @param type The credential type + * @param value The credential value + * @param order The credential order * @param enabled Whether the credential should be enabled */ @Override @@ -273,7 +305,8 @@ public void setCredential(String type, String value, int order, boolean enabled) /** * Sets a credential with the given key - * @param key The credential key + * + * @param key The credential key * @param credential The credential object to set */ @Override @@ -286,6 +319,7 @@ public void setCredential(String key, Credential credential) { /** * Gets the value of a credential by its key + * * @param key The credential key * @return The credential value if found, null otherwise */ @@ -299,6 +333,7 @@ public Object getCredentialValue(String key) { /** * Removes a credential by its key + * * @param key The credential key to remove */ public void removeCredential(String key) { @@ -311,8 +346,9 @@ public void removeCredential(String key) { /** * Checks if a credential is set and has a value + * * @param key The credential key to check - * @return true if credential exists and has a value, false otherwise + * @return true if a credential exists and has a value, false otherwise */ public boolean isCredentialSet(String key) { if (this.credentials == null) { @@ -324,6 +360,7 @@ public boolean isCredentialSet(String key) { /** * Gets all credential keys + * * @return Set of credential keys, empty set if no credentials exist */ public Set getCredentialsKeys() { @@ -334,10 +371,11 @@ public Set getCredentialsKeys() { } /** - * Checks if the user is in ACTIVE state - * @return true if user state is ACTIVE, false otherwise + * Checks if the user is in an ACTIVE state + * + * @return true if the user state is ACTIVE, false otherwise */ public boolean isActive() { return this.state.equals(UserState.ACTIVE); } -} \ No newline at end of file +} diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java index 4989628f1a..b6caecd4cd 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java @@ -38,14 +38,16 @@ public class User { public User(AbstractUser user) { Attribute> enabledCredentialsAttribute = new Attribute<>(); - enabledCredentialsAttribute.setValue(user.getCredentials() - .values().stream() - .filter(java.util.Objects::nonNull) - .filter(Credential::isEnabled) - .map(Credential::getType) - .filter(java.util.Objects::nonNull) - .collect(Collectors.toSet())); - enabledCredentialsAttribute.setRequired(true); + if (user instanceof com.netgrif.application.engine.objects.auth.domain.User userr) { + enabledCredentialsAttribute.setValue(userr.getCredentials() + .values().stream() + .filter(java.util.Objects::nonNull) + .filter(Credential::isEnabled) + .map(Credential::getType) + .filter(java.util.Objects::nonNull) + .collect(Collectors.toSet())); + enabledCredentialsAttribute.setRequired(true); + } id = user.getStringId(); username = user.getUsername(); From ca8a6d08bb4c95a145ce626dfc333030ca285f70 Mon Sep 17 00:00:00 2001 From: Milan Mladoniczky <6153201+tuplle@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:39:59 +0200 Subject: [PATCH 6/8] [NAE-2173] Password change - Change credentials visibility in `User` to private --- .../netgrif/application/engine/objects/auth/domain/User.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java index d9d51362b9..daf27c468e 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java @@ -51,7 +51,7 @@ public class User extends AbstractUser implements Serializable { /** * Map containing user's credentials with credential type as key */ - protected Map> credentials; + private Map> credentials; /** * Default constructor initializing a new User with a generated ObjectId From bc3dd08e8392ee31592d1ce5fab2e47da67adeae Mon Sep 17 00:00:00 2001 From: Milan Mladoniczky <6153201+tuplle@users.noreply.github.com> Date: Fri, 5 Sep 2025 22:03:10 +0200 Subject: [PATCH 7/8] [NAE-2173] Password change - Changed log level in `UserServiceImpl` from trace to debug for better verbosity. - Improved null safety in `User` initialization and credential handling. - Set default value for `credentials` in `User` to avoid null-pointer issues. - Replaced `.equals()` with `==` for better performance checking `UserState`. --- .../engine/objects/auth/domain/User.java | 4 ++-- .../engine/auth/service/UserServiceImpl.java | 2 +- .../engine/auth/web/responsebodies/User.java | 22 +++++++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java index daf27c468e..be637542de 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java @@ -51,7 +51,7 @@ public class User extends AbstractUser implements Serializable { /** * Map containing user's credentials with credential type as key */ - private Map> credentials; + private Map> credentials = new HashMap<>(); /** * Default constructor initializing a new User with a generated ObjectId @@ -376,6 +376,6 @@ public Set getCredentialsKeys() { * @return true if the user state is ACTIVE, false otherwise */ public boolean isActive() { - return this.state.equals(UserState.ACTIVE); + return this.state == UserState.ACTIVE; } } diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java index 15053c6e3d..de9301be4d 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java @@ -268,7 +268,7 @@ public AbstractUser changePassword(AbstractUser user, String newPassword, String throw new IllegalArgumentException("Old password does not match."); } - log.trace("Setting password for user [{}]", user.getUsername()); + log.debug("Setting password for user [{}]", user.getUsername()); user.setPassword(passwordEncoder.encode(newPassword)); return saveUser(user); } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java index b6caecd4cd..2f7d39d28d 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java @@ -39,13 +39,15 @@ public class User { public User(AbstractUser user) { Attribute> enabledCredentialsAttribute = new Attribute<>(); if (user instanceof com.netgrif.application.engine.objects.auth.domain.User userr) { - enabledCredentialsAttribute.setValue(userr.getCredentials() - .values().stream() - .filter(java.util.Objects::nonNull) - .filter(Credential::isEnabled) - .map(Credential::getType) - .filter(java.util.Objects::nonNull) - .collect(Collectors.toSet())); + Map> credentials = userr.getCredentials(); + enabledCredentialsAttribute.setValue( + (credentials == null ? java.util.Map.>of() : credentials) + .values().stream() + .filter(java.util.Objects::nonNull) + .filter(Credential::isEnabled) + .map(Credential::getType) + .filter(java.util.Objects::nonNull) + .collect(Collectors.toSet())); enabledCredentialsAttribute.setRequired(true); } @@ -56,11 +58,13 @@ public User(AbstractUser user) { avatar = user.getAvatar(); firstName = user.getFirstName(); lastName = user.getLastName(); - fullName = user.getName(); + fullName = user.getFullName(); attributes = user.getAttributes() != null ? new java.util.HashMap<>(user.getAttributes()) : new java.util.HashMap<>(); - attributes.put(ATTR_ENABLED_CREDENTIALS, enabledCredentialsAttribute); + if (enabledCredentialsAttribute.getValue() != null) { + attributes.put(ATTR_ENABLED_CREDENTIALS, enabledCredentialsAttribute); + } if (user instanceof com.netgrif.application.engine.objects.auth.domain.User u) { createdAt = u.getCreatedAt(); enabled = u.isActive(); From 56cc11fecd935c9918004dccd3763e570916e01c Mon Sep 17 00:00:00 2001 From: Milan Mladoniczky <6153201+tuplle@users.noreply.github.com> Date: Sat, 6 Sep 2025 03:33:10 +0200 Subject: [PATCH 8/8] [NAE-2173] Password change - Renamed variable `userr` to `domainUser` for improved clarity and consistency. - Added null and empty checks for `enabledCredentialsAttribute` to prevent potential runtime issues. --- .../application/engine/auth/web/responsebodies/User.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java index 2f7d39d28d..42605f8591 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/User.java @@ -38,8 +38,8 @@ public class User { public User(AbstractUser user) { Attribute> enabledCredentialsAttribute = new Attribute<>(); - if (user instanceof com.netgrif.application.engine.objects.auth.domain.User userr) { - Map> credentials = userr.getCredentials(); + if (user instanceof com.netgrif.application.engine.objects.auth.domain.User domainUser) { + Map> credentials = domainUser.getCredentials(); enabledCredentialsAttribute.setValue( (credentials == null ? java.util.Map.>of() : credentials) .values().stream() @@ -62,7 +62,7 @@ public User(AbstractUser user) { attributes = user.getAttributes() != null ? new java.util.HashMap<>(user.getAttributes()) : new java.util.HashMap<>(); - if (enabledCredentialsAttribute.getValue() != null) { + if (enabledCredentialsAttribute.getValue() != null && !enabledCredentialsAttribute.getValue().isEmpty()) { attributes.put(ATTR_ENABLED_CREDENTIALS, enabledCredentialsAttribute); } if (user instanceof com.netgrif.application.engine.objects.auth.domain.User u) {