Move lastLoginTs and failedLoginAttempts from user's additionalInfo
This commit is contained in:
parent
a4370d9b87
commit
c676ebb267
25
application/src/main/data/upgrade/3.7.1/schema_update.sql
Normal file
25
application/src/main/data/upgrade/3.7.1/schema_update.sql
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
--
|
||||||
|
-- Copyright © 2016-2024 The Thingsboard Authors
|
||||||
|
--
|
||||||
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
-- you may not use this file except in compliance with the License.
|
||||||
|
-- You may obtain a copy of the License at
|
||||||
|
--
|
||||||
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
--
|
||||||
|
-- Unless required by applicable law or agreed to in writing, software
|
||||||
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
-- See the License for the specific language governing permissions and
|
||||||
|
-- limitations under the License.
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS last_login_ts BIGINT;
|
||||||
|
UPDATE user_credentials c SET last_login_ts = (SELECT (additional_info::json ->> 'lastLoginTs')::bigint FROM tb_user u WHERE u.id = c.user_id)
|
||||||
|
WHERE last_login_ts IS NULL;
|
||||||
|
|
||||||
|
ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS failed_login_attempts INT;
|
||||||
|
UPDATE user_credentials c SET failed_login_attempts = (SELECT (additional_info::json ->> 'failedLoginAttempts')::int FROM tb_user u WHERE u.id = c.user_id)
|
||||||
|
WHERE failed_login_attempts IS NULL;
|
||||||
|
|
||||||
|
UPDATE tb_user SET additional_info = (additional_info::jsonb - 'lastLoginTs' - 'failedLoginAttempts')::text WHERE additional_info IS NOT NULL AND additional_info != 'null';
|
||||||
@ -109,6 +109,8 @@ import static org.thingsboard.server.controller.ControllerConstants.USER_ID_PARA
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.USER_TEXT_SEARCH_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.USER_TEXT_SEARCH_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
|
||||||
import static org.thingsboard.server.dao.entity.BaseEntityService.NULL_CUSTOMER_ID;
|
import static org.thingsboard.server.dao.entity.BaseEntityService.NULL_CUSTOMER_ID;
|
||||||
|
import static org.thingsboard.server.dao.user.UserServiceImpl.LAST_LOGIN_TS;
|
||||||
|
import static org.thingsboard.server.dao.user.UserServiceImpl.USER_CREDENTIALS_ENABLED;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RestController
|
@RestController
|
||||||
@ -151,9 +153,10 @@ public class UserController extends BaseController {
|
|||||||
processDashboardIdFromAdditionalInfo(additionalInfo, DEFAULT_DASHBOARD);
|
processDashboardIdFromAdditionalInfo(additionalInfo, DEFAULT_DASHBOARD);
|
||||||
processDashboardIdFromAdditionalInfo(additionalInfo, HOME_DASHBOARD);
|
processDashboardIdFromAdditionalInfo(additionalInfo, HOME_DASHBOARD);
|
||||||
UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId());
|
UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId());
|
||||||
if (userCredentials.isEnabled() && !additionalInfo.has("userCredentialsEnabled")) {
|
if (userCredentials.isEnabled() && !additionalInfo.has(USER_CREDENTIALS_ENABLED)) {
|
||||||
additionalInfo.put("userCredentialsEnabled", true);
|
additionalInfo.put(USER_CREDENTIALS_ENABLED, true);
|
||||||
}
|
}
|
||||||
|
additionalInfo.put(LAST_LOGIN_TS, userCredentials.getLastLoginTs());
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,6 @@ import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
|
|||||||
import org.thingsboard.server.dao.eventsourcing.RelationActionEvent;
|
import org.thingsboard.server.dao.eventsourcing.RelationActionEvent;
|
||||||
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
|
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
|
||||||
import org.thingsboard.server.dao.tenant.TenantService;
|
import org.thingsboard.server.dao.tenant.TenantService;
|
||||||
import org.thingsboard.server.dao.user.UserServiceImpl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event listener does not support async event processing because relay on ThreadLocal
|
* This event listener does not support async event processing because relay on ThreadLocal
|
||||||
@ -231,8 +230,6 @@ public class EdgeEventSourcingListener {
|
|||||||
user.setAdditionalInfo(null);
|
user.setAdditionalInfo(null);
|
||||||
}
|
}
|
||||||
if (user.getAdditionalInfo() instanceof ObjectNode additionalInfo) {
|
if (user.getAdditionalInfo() instanceof ObjectNode additionalInfo) {
|
||||||
additionalInfo.remove(UserServiceImpl.FAILED_LOGIN_ATTEMPTS);
|
|
||||||
additionalInfo.remove(UserServiceImpl.LAST_LOGIN_TS);
|
|
||||||
if (additionalInfo.isEmpty()) {
|
if (additionalInfo.isEmpty()) {
|
||||||
user.setAdditionalInfo(null);
|
user.setAdditionalInfo(null);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -265,7 +265,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (actionType == ActionType.LOGIN && e == null) {
|
if (actionType == ActionType.LOGIN && e == null) {
|
||||||
userService.setLastLoginTs(user.getTenantId(), user.getId());
|
userService.updateLastLoginTs(user.getTenantId(), user.getId());
|
||||||
}
|
}
|
||||||
auditLogService.logEntityAction(
|
auditLogService.logEntityAction(
|
||||||
user.getTenantId(), user.getCustomerId(), user.getId(),
|
user.getTenantId(), user.getCustomerId(), user.getId(),
|
||||||
|
|||||||
@ -97,7 +97,7 @@ public interface UserService extends EntityDaoService {
|
|||||||
|
|
||||||
int increaseFailedLoginAttempts(TenantId tenantId, UserId userId);
|
int increaseFailedLoginAttempts(TenantId tenantId, UserId userId);
|
||||||
|
|
||||||
void setLastLoginTs(TenantId tenantId, UserId userId);
|
void updateLastLoginTs(TenantId tenantId, UserId userId);
|
||||||
|
|
||||||
void saveMobileSession(TenantId tenantId, UserId userId, String mobileToken, MobileSessionInfo sessionInfo);
|
void saveMobileSession(TenantId tenantId, UserId userId, String mobileToken, MobileSessionInfo sessionInfo);
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,8 @@ public class UserCredentials extends BaseDataWithAdditionalInfo<UserCredentialsI
|
|||||||
private Long activateTokenExpTime;
|
private Long activateTokenExpTime;
|
||||||
private String resetToken;
|
private String resetToken;
|
||||||
private Long resetTokenExpTime;
|
private Long resetTokenExpTime;
|
||||||
|
private Long lastLoginTs;
|
||||||
|
private Integer failedLoginAttempts;
|
||||||
|
|
||||||
public UserCredentials() {
|
public UserCredentials() {
|
||||||
super();
|
super();
|
||||||
|
|||||||
@ -82,7 +82,8 @@ public class ModelConstants {
|
|||||||
public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_EXP_TIME_PROPERTY = "activate_token_exp_time";
|
public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_EXP_TIME_PROPERTY = "activate_token_exp_time";
|
||||||
public static final String USER_CREDENTIALS_RESET_TOKEN_PROPERTY = "reset_token";
|
public static final String USER_CREDENTIALS_RESET_TOKEN_PROPERTY = "reset_token";
|
||||||
public static final String USER_CREDENTIALS_RESET_TOKEN_EXP_TIME_PROPERTY = "reset_token_exp_time";
|
public static final String USER_CREDENTIALS_RESET_TOKEN_EXP_TIME_PROPERTY = "reset_token_exp_time";
|
||||||
public static final String USER_CREDENTIALS_ADDITIONAL_PROPERTY = "additional_info";
|
public static final String USER_CREDENTIALS_LAST_LOGIN_TS_PROPERTY = "last_login_ts";
|
||||||
|
public static final String USER_CREDENTIALS_FAILED_LOGIN_ATTEMPTS_PROPERTY = "failed_login_attempts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User settings constants.
|
* User settings constants.
|
||||||
|
|||||||
@ -60,18 +60,21 @@ public final class UserCredentialsEntity extends BaseSqlEntity<UserCredentials>
|
|||||||
private Long resetTokenExpTime;
|
private Long resetTokenExpTime;
|
||||||
|
|
||||||
@Convert(converter = JsonConverter.class)
|
@Convert(converter = JsonConverter.class)
|
||||||
@Column(name = ModelConstants.USER_CREDENTIALS_ADDITIONAL_PROPERTY)
|
@Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY)
|
||||||
private JsonNode additionalInfo;
|
private JsonNode additionalInfo;
|
||||||
|
|
||||||
|
@Column(name = ModelConstants.USER_CREDENTIALS_LAST_LOGIN_TS_PROPERTY)
|
||||||
|
private Long lastLoginTs;
|
||||||
|
|
||||||
|
@Column(name = ModelConstants.USER_CREDENTIALS_FAILED_LOGIN_ATTEMPTS_PROPERTY)
|
||||||
|
private Integer failedLoginAttempts;
|
||||||
|
|
||||||
public UserCredentialsEntity() {
|
public UserCredentialsEntity() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserCredentialsEntity(UserCredentials userCredentials) {
|
public UserCredentialsEntity(UserCredentials userCredentials) {
|
||||||
if (userCredentials.getId() != null) {
|
super(userCredentials);
|
||||||
this.setUuid(userCredentials.getId().getId());
|
|
||||||
}
|
|
||||||
this.setCreatedTime(userCredentials.getCreatedTime());
|
|
||||||
if (userCredentials.getUserId() != null) {
|
if (userCredentials.getUserId() != null) {
|
||||||
this.userId = userCredentials.getUserId().getId();
|
this.userId = userCredentials.getUserId().getId();
|
||||||
}
|
}
|
||||||
@ -82,6 +85,8 @@ public final class UserCredentialsEntity extends BaseSqlEntity<UserCredentials>
|
|||||||
this.resetToken = userCredentials.getResetToken();
|
this.resetToken = userCredentials.getResetToken();
|
||||||
this.resetTokenExpTime = userCredentials.getResetTokenExpTime();
|
this.resetTokenExpTime = userCredentials.getResetTokenExpTime();
|
||||||
this.additionalInfo = userCredentials.getAdditionalInfo();
|
this.additionalInfo = userCredentials.getAdditionalInfo();
|
||||||
|
this.lastLoginTs = userCredentials.getLastLoginTs();
|
||||||
|
this.failedLoginAttempts = userCredentials.getFailedLoginAttempts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -98,6 +103,8 @@ public final class UserCredentialsEntity extends BaseSqlEntity<UserCredentials>
|
|||||||
userCredentials.setResetToken(resetToken);
|
userCredentials.setResetToken(resetToken);
|
||||||
userCredentials.setResetTokenExpTime(resetTokenExpTime);
|
userCredentials.setResetTokenExpTime(resetTokenExpTime);
|
||||||
userCredentials.setAdditionalInfo(additionalInfo);
|
userCredentials.setAdditionalInfo(additionalInfo);
|
||||||
|
userCredentials.setLastLoginTs(lastLoginTs);
|
||||||
|
userCredentials.setFailedLoginAttempts(failedLoginAttempts);
|
||||||
return userCredentials;
|
return userCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -69,4 +69,19 @@ public class JpaUserCredentialsDao extends JpaAbstractDao<UserCredentialsEntity,
|
|||||||
userCredentialsRepository.removeByUserId(userId.getId());
|
userCredentialsRepository.removeByUserId(userId.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLastLoginTs(TenantId tenantId, UserId userId, long lastLoginTs) {
|
||||||
|
userCredentialsRepository.updateLastLoginTsByUserId(userId.getId(), lastLoginTs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int incrementFailedLoginAttempts(TenantId tenantId, UserId userId) {
|
||||||
|
return userCredentialsRepository.incrementFailedLoginAttemptsByUserId(userId.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFailedLoginAttempts(TenantId tenantId, UserId userId, int failedLoginAttempts) {
|
||||||
|
userCredentialsRepository.updateFailedLoginAttemptsByUserId(userId.getId(), failedLoginAttempts);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
package org.thingsboard.server.dao.sql.user;
|
package org.thingsboard.server.dao.sql.user;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.thingsboard.server.dao.model.sql.UserCredentialsEntity;
|
import org.thingsboard.server.dao.model.sql.UserCredentialsEntity;
|
||||||
|
|
||||||
@ -35,4 +37,20 @@ public interface UserCredentialsRepository extends JpaRepository<UserCredentials
|
|||||||
@Transactional
|
@Transactional
|
||||||
void removeByUserId(UUID userId);
|
void removeByUserId(UUID userId);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Modifying
|
||||||
|
@Query("UPDATE UserCredentialsEntity SET lastLoginTs = :lastLoginTs WHERE userId = :userId")
|
||||||
|
void updateLastLoginTsByUserId(UUID userId, long lastLoginTs);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Modifying
|
||||||
|
@Query(value = "UPDATE user_credentials SET failed_login_attempts = coalesce(failed_login_attempts, 0) + 1 " +
|
||||||
|
"WHERE user_id = :userId RETURNING failed_login_attempts", nativeQuery = true)
|
||||||
|
int incrementFailedLoginAttemptsByUserId(UUID userId);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Modifying
|
||||||
|
@Query("UPDATE UserCredentialsEntity SET failedLoginAttempts = :failedLoginAttempts WHERE userId = :userId")
|
||||||
|
void updateFailedLoginAttemptsByUserId(UUID userId, int failedLoginAttempts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,4 +61,10 @@ public interface UserCredentialsDao extends Dao<UserCredentials> {
|
|||||||
|
|
||||||
void removeByUserId(TenantId tenantId, UserId userId);
|
void removeByUserId(TenantId tenantId, UserId userId);
|
||||||
|
|
||||||
|
void setLastLoginTs(TenantId tenantId, UserId userId, long lastLoginTs);
|
||||||
|
|
||||||
|
int incrementFailedLoginAttempts(TenantId tenantId, UserId userId);
|
||||||
|
|
||||||
|
void setFailedLoginAttempts(TenantId tenantId, UserId userId, int failedLoginAttempts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,8 +18,6 @@ package org.thingsboard.server.dao.user;
|
|||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.BooleanNode;
|
import com.fasterxml.jackson.databind.node.BooleanNode;
|
||||||
import com.fasterxml.jackson.databind.node.IntNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.LongNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -86,16 +84,13 @@ import static org.thingsboard.server.dao.service.Validator.validateString;
|
|||||||
public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, User, UserCacheEvictEvent> implements UserService {
|
public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, User, UserCacheEvictEvent> implements UserService {
|
||||||
|
|
||||||
public static final String USER_PASSWORD_HISTORY = "userPasswordHistory";
|
public static final String USER_PASSWORD_HISTORY = "userPasswordHistory";
|
||||||
|
public static final String USER_CREDENTIALS_ENABLED = "userCredentialsEnabled";
|
||||||
public static final String LAST_LOGIN_TS = "lastLoginTs";
|
public static final String LAST_LOGIN_TS = "lastLoginTs";
|
||||||
public static final String FAILED_LOGIN_ATTEMPTS = "failedLoginAttempts";
|
|
||||||
|
|
||||||
private static final int DEFAULT_TOKEN_LENGTH = 30;
|
private static final int DEFAULT_TOKEN_LENGTH = 30;
|
||||||
public static final String INCORRECT_USER_ID = "Incorrect userId ";
|
public static final String INCORRECT_USER_ID = "Incorrect userId ";
|
||||||
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
|
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
|
||||||
|
|
||||||
private static final String USER_CREDENTIALS_ENABLED = "userCredentialsEnabled";
|
|
||||||
|
|
||||||
@Value("${security.user_login_case_sensitive:true}")
|
@Value("${security.user_login_case_sensitive:true}")
|
||||||
private boolean userLoginCaseSensitive;
|
private boolean userLoginCaseSensitive;
|
||||||
|
|
||||||
@ -428,6 +423,7 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U
|
|||||||
customerUsersRemover.removeEntities(tenantId, customerId);
|
customerUsersRemover.removeEntities(tenantId, customerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public void setUserCredentialsEnabled(TenantId tenantId, UserId userId, boolean enabled) {
|
public void setUserCredentialsEnabled(TenantId tenantId, UserId userId, boolean enabled) {
|
||||||
log.trace("Executing setUserCredentialsEnabled [{}], [{}]", userId, enabled);
|
log.trace("Executing setUserCredentialsEnabled [{}], [{}]", userId, enabled);
|
||||||
@ -438,30 +434,22 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U
|
|||||||
|
|
||||||
User user = findUserById(tenantId, userId);
|
User user = findUserById(tenantId, userId);
|
||||||
user.setAdditionalInfoField(USER_CREDENTIALS_ENABLED, BooleanNode.valueOf(enabled));
|
user.setAdditionalInfoField(USER_CREDENTIALS_ENABLED, BooleanNode.valueOf(enabled));
|
||||||
if (enabled) {
|
|
||||||
resetFailedLoginAttempts(user);
|
|
||||||
}
|
|
||||||
saveUser(tenantId, user);
|
saveUser(tenantId, user);
|
||||||
|
if (enabled) {
|
||||||
|
resetFailedLoginAttempts(tenantId, userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resetFailedLoginAttempts(TenantId tenantId, UserId userId) {
|
public void resetFailedLoginAttempts(TenantId tenantId, UserId userId) {
|
||||||
log.trace("Executing onUserLoginSuccessful [{}]", userId);
|
log.trace("Executing resetFailedLoginAttempts [{}]", userId);
|
||||||
User user = findUserById(tenantId, userId);
|
userCredentialsDao.setFailedLoginAttempts(tenantId, userId, 0);
|
||||||
resetFailedLoginAttempts(user);
|
|
||||||
saveUser(tenantId, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetFailedLoginAttempts(User user) {
|
|
||||||
user.setAdditionalInfoField(FAILED_LOGIN_ATTEMPTS, IntNode.valueOf(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLastLoginTs(TenantId tenantId, UserId userId) {
|
public void updateLastLoginTs(TenantId tenantId, UserId userId) {
|
||||||
User user = findUserById(tenantId, userId);
|
userCredentialsDao.setLastLoginTs(tenantId, userId, System.currentTimeMillis());
|
||||||
user.setAdditionalInfoField(LAST_LOGIN_TS, new LongNode(System.currentTimeMillis()));
|
|
||||||
saveUser(tenantId, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -502,18 +490,8 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int increaseFailedLoginAttempts(TenantId tenantId, UserId userId) {
|
public int increaseFailedLoginAttempts(TenantId tenantId, UserId userId) {
|
||||||
log.trace("Executing onUserLoginIncorrectCredentials [{}]", userId);
|
log.trace("Executing increaseFailedLoginAttempts [{}]", userId);
|
||||||
User user = findUserById(tenantId, userId);
|
return userCredentialsDao.incrementFailedLoginAttempts(tenantId, userId);
|
||||||
int failedLoginAttempts = increaseFailedLoginAttempts(user);
|
|
||||||
saveUser(tenantId, user);
|
|
||||||
return failedLoginAttempts;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int increaseFailedLoginAttempts(User user) {
|
|
||||||
int failedLoginAttempts = user.getAdditionalInfoField(FAILED_LOGIN_ATTEMPTS, JsonNode::asInt, 0);
|
|
||||||
failedLoginAttempts++;
|
|
||||||
user.setAdditionalInfoField(FAILED_LOGIN_ATTEMPTS, new IntNode(failedLoginAttempts));
|
|
||||||
return failedLoginAttempts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePasswordHistory(UserCredentials userCredentials) {
|
private void updatePasswordHistory(UserCredentials userCredentials) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user