Refactoring
This commit is contained in:
		
							parent
							
								
									215a44b7c7
								
							
						
					
					
						commit
						6d34aa237c
					
				@ -43,6 +43,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.security.UserCredentials;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserSessionInvalidationEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.model.SecuritySettings;
 | 
			
		||||
import org.thingsboard.server.common.data.security.model.UserPasswordPolicy;
 | 
			
		||||
import org.thingsboard.server.dao.audit.AuditLogService;
 | 
			
		||||
@ -125,7 +127,7 @@ public class AuthController extends BaseController {
 | 
			
		||||
 | 
			
		||||
            sendEntityNotificationMsg(getTenantId(), userCredentials.getUserId(), EdgeEventActionType.CREDENTIALS_UPDATED);
 | 
			
		||||
 | 
			
		||||
            eventPublisher.publishEvent(new UserAuthDataChangedEvent(securityUser.getId(), securityUser.getSessionId(), false));
 | 
			
		||||
            eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
            ObjectNode response = JacksonUtil.newObjectNode();
 | 
			
		||||
            response.put("token", tokenFactory.createAccessJwtToken(securityUser).getToken());
 | 
			
		||||
            response.put("refreshToken", tokenFactory.createRefreshToken(securityUser).getToken());
 | 
			
		||||
@ -303,7 +305,7 @@ public class AuthController extends BaseController {
 | 
			
		||||
                String email = user.getEmail();
 | 
			
		||||
                mailService.sendPasswordWasResetEmail(loginUrl, email);
 | 
			
		||||
 | 
			
		||||
                eventPublisher.publishEvent(new UserAuthDataChangedEvent(securityUser.getId(), securityUser.getSessionId(), false));
 | 
			
		||||
                eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
 | 
			
		||||
                return tokenFactory.createTokenPair(securityUser);
 | 
			
		||||
            } else {
 | 
			
		||||
@ -359,7 +361,7 @@ public class AuthController extends BaseController {
 | 
			
		||||
                    user.getTenantId(), user.getCustomerId(), user.getId(),
 | 
			
		||||
                    user.getName(), user.getId(), null, ActionType.LOGOUT, null, clientAddress, browser, os, device);
 | 
			
		||||
 | 
			
		||||
            eventPublisher.publishEvent(new UserAuthDataChangedEvent(user.getId(), user.getSessionId(), false));
 | 
			
		||||
            eventPublisher.publishEvent(new UserSessionInvalidationEvent(user.getSessionId()));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.page.PageLink;
 | 
			
		||||
import org.thingsboard.server.common.data.security.Authority;
 | 
			
		||||
import org.thingsboard.server.common.data.security.UserCredentials;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.entitiy.user.TbUserService;
 | 
			
		||||
import org.thingsboard.server.service.security.model.JwtTokenPair;
 | 
			
		||||
@ -371,7 +372,7 @@ public class UserController extends BaseController {
 | 
			
		||||
            userService.setUserCredentialsEnabled(tenantId, userId, userCredentialsEnabled);
 | 
			
		||||
 | 
			
		||||
            if (!userCredentialsEnabled) {
 | 
			
		||||
                eventPublisher.publishEvent(new UserAuthDataChangedEvent(userId, null, true));
 | 
			
		||||
                eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(userId));
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
 | 
			
		||||
@ -19,16 +19,14 @@ import io.jsonwebtoken.Claims;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.context.event.EventListener;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.event.TransactionalEventListener;
 | 
			
		||||
import org.thingsboard.server.cache.usersUpdateTime.UsersUpdateTimeCacheEvictEvent;
 | 
			
		||||
import org.thingsboard.server.cache.TbCacheValueWrapper;
 | 
			
		||||
import org.thingsboard.server.cache.TbTransactionalCache;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.model.JwtToken;
 | 
			
		||||
import org.thingsboard.server.config.JwtSettings;
 | 
			
		||||
import org.thingsboard.server.dao.entity.AbstractCachedEntityService;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
 | 
			
		||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
 | 
			
		||||
@ -36,13 +34,14 @@ import static java.util.concurrent.TimeUnit.SECONDS;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
public class TokenOutdatingService extends AbstractCachedEntityService<UserId, HashMap<String, Long>, UsersUpdateTimeCacheEvictEvent> {
 | 
			
		||||
public class TokenOutdatingService {
 | 
			
		||||
    private final TbTransactionalCache<String, Long> cache;
 | 
			
		||||
    private final JwtTokenFactory tokenFactory;
 | 
			
		||||
    private final JwtSettings jwtSettings;
 | 
			
		||||
 | 
			
		||||
    @EventListener(classes = UserAuthDataChangedEvent.class)
 | 
			
		||||
    public void onUserAuthDataChanged(UserAuthDataChangedEvent event) {
 | 
			
		||||
        processUserSessions(event);
 | 
			
		||||
        cache.put(event.getId(), event.getTs());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isOutdated(JwtToken token, UserId userId) {
 | 
			
		||||
@ -50,48 +49,36 @@ public class TokenOutdatingService extends AbstractCachedEntityService<UserId, H
 | 
			
		||||
        long issueTime = claims.getIssuedAt().getTime();
 | 
			
		||||
 | 
			
		||||
        String sessionId = claims.get("sessionId", String.class);
 | 
			
		||||
        return Optional.ofNullable(cache.get(userId))
 | 
			
		||||
                .map(outdatageTime -> {
 | 
			
		||||
                    if (outdatageTime.get().get(sessionId) != null && System.currentTimeMillis() - outdatageTime.get().get(sessionId) <= SECONDS.toMillis(jwtSettings.getRefreshTokenExpTime())) {
 | 
			
		||||
                        return MILLISECONDS.toSeconds(issueTime) < MILLISECONDS.toSeconds(outdatageTime.get().get(sessionId));
 | 
			
		||||
 | 
			
		||||
        Boolean isUserIdOutdated = Optional.ofNullable(cache.get(userId.toString()))
 | 
			
		||||
                .map(outdatageTimeByUserId -> {
 | 
			
		||||
                    if (refreshTokenNotExpired(outdatageTimeByUserId.get(), System.currentTimeMillis())) {
 | 
			
		||||
                        return accessTokenNotExpired(issueTime, outdatageTimeByUserId.get());
 | 
			
		||||
                    } else {
 | 
			
		||||
                        /*
 | 
			
		||||
                         * Means that since the outdating has passed more than
 | 
			
		||||
                         * the lifetime of refresh token (the longest lived)
 | 
			
		||||
                         * and there is no need to store outdatage time anymore
 | 
			
		||||
                         * as all the tokens issued before the outdatage time
 | 
			
		||||
                         * are now expired by themselves
 | 
			
		||||
                         * */
 | 
			
		||||
                        handleEvictEvent(new UsersUpdateTimeCacheEvictEvent(userId, sessionId));
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
                .orElse(false);
 | 
			
		||||
 | 
			
		||||
        if (!isUserIdOutdated) {
 | 
			
		||||
            return Optional.ofNullable(cache.get(sessionId)).map(outdatageTimeBySessionId -> {
 | 
			
		||||
                        if (refreshTokenNotExpired(outdatageTimeBySessionId.get(), System.currentTimeMillis())) {
 | 
			
		||||
                            return accessTokenNotExpired(issueTime, outdatageTimeBySessionId.get());
 | 
			
		||||
                        } else {
 | 
			
		||||
                            return false;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
            ).orElse(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return isUserIdOutdated;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @TransactionalEventListener(classes = UsersUpdateTimeCacheEvictEvent.class)
 | 
			
		||||
    @Override
 | 
			
		||||
    public void handleEvictEvent(UsersUpdateTimeCacheEvictEvent event) {
 | 
			
		||||
        HashMap<String, Long> userSessions = cache.get(event.getUserId()).get();
 | 
			
		||||
        if (userSessions != null) {
 | 
			
		||||
            userSessions.remove(event.getSessionId());
 | 
			
		||||
            cache.put(event.getUserId(), userSessions);
 | 
			
		||||
        }
 | 
			
		||||
    private boolean accessTokenNotExpired(long issueTime, Long outdatageTime) {
 | 
			
		||||
        return MILLISECONDS.toSeconds(issueTime) < MILLISECONDS.toSeconds(outdatageTime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void processUserSessions(UserAuthDataChangedEvent event) {
 | 
			
		||||
        if (cache.get(event.getUserId()) != null) {
 | 
			
		||||
            HashMap<String, Long> userSessions = cache.get(event.getUserId()).get();
 | 
			
		||||
            if (event.isDropAllSessions()) {
 | 
			
		||||
                userSessions.replaceAll((k, v) -> event.getTs());
 | 
			
		||||
            } else {
 | 
			
		||||
                userSessions.put(event.getSessionId(), event.getTs());
 | 
			
		||||
            }
 | 
			
		||||
            cache.put(event.getUserId(), userSessions);
 | 
			
		||||
        } else {
 | 
			
		||||
            cache.put(event.getUserId(), new HashMap<>() {{
 | 
			
		||||
                put(event.getSessionId(), event.getTs());
 | 
			
		||||
            }});
 | 
			
		||||
        }
 | 
			
		||||
    private boolean refreshTokenNotExpired(Long outdatageTime, long currentTime) {
 | 
			
		||||
        return currentTime - outdatageTime <= SECONDS.toMillis(jwtSettings.getRefreshTokenExpTime());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -66,7 +66,7 @@ public class RefreshTokenAuthenticationProvider implements AuthenticationProvide
 | 
			
		||||
        } else {
 | 
			
		||||
            securityUser = authenticateByPublicId(principal.getValue());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        securityUser.setSessionId(unsafeUser.getSessionId());
 | 
			
		||||
        if (tokenOutdatingService.isOutdated(rawAccessToken, securityUser.getId())) {
 | 
			
		||||
            throw new CredentialsExpiredException("Token is outdated");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -120,7 +120,9 @@ public class JwtTokenFactory {
 | 
			
		||||
        if (customerId != null) {
 | 
			
		||||
            securityUser.setCustomerId(new CustomerId(UUID.fromString(customerId)));
 | 
			
		||||
        }
 | 
			
		||||
        securityUser.setSessionId(claims.get(SESSION_ID, String.class));
 | 
			
		||||
        if (claims.get(SESSION_ID, String.class) != null) {
 | 
			
		||||
            securityUser.setSessionId(claims.get(SESSION_ID, String.class));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        UserPrincipal principal;
 | 
			
		||||
        if (securityUser.getAuthority() != Authority.PRE_VERIFICATION_TOKEN) {
 | 
			
		||||
@ -163,7 +165,9 @@ public class JwtTokenFactory {
 | 
			
		||||
        UserPrincipal principal = new UserPrincipal(isPublic ? UserPrincipal.Type.PUBLIC_ID : UserPrincipal.Type.USER_NAME, subject);
 | 
			
		||||
        SecurityUser securityUser = new SecurityUser(new UserId(UUID.fromString(claims.get(USER_ID, String.class))));
 | 
			
		||||
        securityUser.setUserPrincipal(principal);
 | 
			
		||||
        securityUser.setSessionId(claims.get(SESSION_ID, String.class));
 | 
			
		||||
        if (claims.get(SESSION_ID, String.class) != null) {
 | 
			
		||||
            securityUser.setSessionId(claims.get(SESSION_ID, String.class));
 | 
			
		||||
        }
 | 
			
		||||
        return securityUser;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,8 @@ import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
import org.thingsboard.server.common.data.security.Authority;
 | 
			
		||||
import org.thingsboard.server.common.data.security.UserCredentials;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserSessionInvalidationEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.model.JwtToken;
 | 
			
		||||
import org.thingsboard.server.dao.customer.CustomerService;
 | 
			
		||||
import org.thingsboard.server.dao.service.DaoSqlTest;
 | 
			
		||||
@ -106,7 +108,7 @@ public class TokenOutdatingTest {
 | 
			
		||||
        JwtToken jwtToken = tokenFactory.createAccessJwtToken(securityUser);
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1); // need to wait before outdating so that outdatage time is strictly after token issue time
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(securityUser.getId(), securityUser.getSessionId(), false));
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
        assertTrue(tokenOutdatingService.isOutdated(jwtToken, securityUser.getId()));
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1);
 | 
			
		||||
@ -124,7 +126,7 @@ public class TokenOutdatingTest {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1);
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(securityUser.getId(), securityUser.getSessionId(), false));
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
 | 
			
		||||
        assertThrows(JwtExpiredTokenException.class, () -> {
 | 
			
		||||
            accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(accessJwtToken));
 | 
			
		||||
@ -140,7 +142,7 @@ public class TokenOutdatingTest {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1);
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(securityUser.getId(), securityUser.getSessionId(), false));
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
 | 
			
		||||
        assertThrows(CredentialsExpiredException.class, () -> {
 | 
			
		||||
            refreshTokenAuthenticationProvider.authenticate(new RefreshAuthenticationToken(refreshJwtToken));
 | 
			
		||||
@ -152,7 +154,7 @@ public class TokenOutdatingTest {
 | 
			
		||||
        JwtToken jwtToken = tokenFactory.createAccessJwtToken(securityUser);
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1);
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(securityUser.getId(), securityUser.getSessionId(), false));
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1);
 | 
			
		||||
 | 
			
		||||
@ -175,7 +177,8 @@ public class TokenOutdatingTest {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1);
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserAuthDataChangedEvent(securityUser.getId(), securityUser.getSessionId(), false));
 | 
			
		||||
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserSessionInvalidationEvent(securityUser.getSessionId()));
 | 
			
		||||
 | 
			
		||||
        assertThrows(JwtExpiredTokenException.class, () -> {
 | 
			
		||||
            accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(getRawJwtToken(jwtToken)));
 | 
			
		||||
@ -186,6 +189,34 @@ public class TokenOutdatingTest {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testResetAllSessions() throws InterruptedException {
 | 
			
		||||
        JwtToken jwtToken = tokenFactory.createAccessJwtToken(securityUser);
 | 
			
		||||
 | 
			
		||||
        SecurityUser anotherSecurityUser = new SecurityUser(securityUser, securityUser.isEnabled(), securityUser.getUserPrincipal());
 | 
			
		||||
        JwtToken anotherJwtToken = tokenFactory.createAccessJwtToken(anotherSecurityUser);
 | 
			
		||||
 | 
			
		||||
        assertDoesNotThrow(() -> {
 | 
			
		||||
            accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(getRawJwtToken(jwtToken)));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertDoesNotThrow(() -> {
 | 
			
		||||
            accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(getRawJwtToken(anotherJwtToken)));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        SECONDS.sleep(1);
 | 
			
		||||
 | 
			
		||||
        tokenOutdatingService.onUserAuthDataChanged(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
 | 
			
		||||
        assertThrows(JwtExpiredTokenException.class, () -> {
 | 
			
		||||
           accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(getRawJwtToken(jwtToken)));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertThrows(JwtExpiredTokenException.class, () -> {
 | 
			
		||||
           accessTokenAuthenticationProvider.authenticate(new JwtAuthenticationToken(getRawJwtToken(anotherJwtToken)));
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private RawAccessJwtToken getRawJwtToken(JwtToken token) {
 | 
			
		||||
        return new RawAccessJwtToken(token.getToken());
 | 
			
		||||
 | 
			
		||||
@ -24,13 +24,10 @@ import org.thingsboard.server.cache.RedisTbTransactionalCache;
 | 
			
		||||
import org.thingsboard.server.cache.TBRedisCacheConfiguration;
 | 
			
		||||
import org.thingsboard.server.cache.TbFSTRedisSerializer;
 | 
			
		||||
import org.thingsboard.server.common.data.CacheConstants;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
 | 
			
		||||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
 | 
			
		||||
@Service("UsersUpdateTimeCache")
 | 
			
		||||
public class UserUpdateTimeRedisCache extends RedisTbTransactionalCache<UserId, HashMap<String, Long>> {
 | 
			
		||||
public class UserUpdateTimeRedisCache extends RedisTbTransactionalCache<String, Long> {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    public UserUpdateTimeRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
 | 
			
		||||
 | 
			
		||||
@ -16,10 +16,8 @@
 | 
			
		||||
package org.thingsboard.server.cache.usersUpdateTime;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class UsersUpdateTimeCacheEvictEvent {
 | 
			
		||||
    private final UserId userId;
 | 
			
		||||
    private final String sessionId;
 | 
			
		||||
    private final String key;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,14 +21,11 @@ import org.springframework.cache.CacheManager;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.thingsboard.server.cache.CaffeineTbTransactionalCache;
 | 
			
		||||
import org.thingsboard.server.common.data.CacheConstants;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
 | 
			
		||||
@Service("UsersUpdateTimeCache")
 | 
			
		||||
public class UsersUpdateTimeCaffeineCache extends CaffeineTbTransactionalCache<UserId, HashMap<String, Long>> {
 | 
			
		||||
public class UsersUpdateTimeCaffeineCache extends CaffeineTbTransactionalCache<String, Long> {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    public UsersUpdateTimeCaffeineCache(CacheManager cacheManager) {
 | 
			
		||||
 | 
			
		||||
@ -20,18 +20,7 @@ import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class UserAuthDataChangedEvent implements Serializable {
 | 
			
		||||
    private final UserId userId;
 | 
			
		||||
    private final String sessionId;
 | 
			
		||||
    private final long ts;
 | 
			
		||||
    private final boolean dropAllSessions;
 | 
			
		||||
 | 
			
		||||
    public UserAuthDataChangedEvent(UserId userId, String sessionId, boolean dropAllSessions) {
 | 
			
		||||
        this.userId = userId;
 | 
			
		||||
        this.sessionId = sessionId;
 | 
			
		||||
        this.dropAllSessions = dropAllSessions;
 | 
			
		||||
        this.ts = System.currentTimeMillis();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public abstract class UserAuthDataChangedEvent implements Serializable {
 | 
			
		||||
    public abstract String getId();
 | 
			
		||||
    public abstract long getTs();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2022 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.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.common.data.security.event;
 | 
			
		||||
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
 | 
			
		||||
@Getter
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
public class UserCredentialsInvalidationEvent extends UserAuthDataChangedEvent {
 | 
			
		||||
    private final UserId userId;
 | 
			
		||||
    private final long ts;
 | 
			
		||||
 | 
			
		||||
    public UserCredentialsInvalidationEvent(UserId userId) {
 | 
			
		||||
        this.userId = userId;
 | 
			
		||||
        this.ts = System.currentTimeMillis();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getId() {
 | 
			
		||||
        return userId.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getTs() {
 | 
			
		||||
        return ts;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,39 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2022 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.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.common.data.security.event;
 | 
			
		||||
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
public class UserSessionInvalidationEvent extends UserAuthDataChangedEvent {
 | 
			
		||||
    private final String sessionId;
 | 
			
		||||
    private final long ts;
 | 
			
		||||
 | 
			
		||||
    public UserSessionInvalidationEvent(String sessionId) {
 | 
			
		||||
        this.sessionId = sessionId;
 | 
			
		||||
        this.ts = System.currentTimeMillis();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getId() {
 | 
			
		||||
        return sessionId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getTs() {
 | 
			
		||||
        return ts;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.page.PageData;
 | 
			
		||||
import org.thingsboard.server.common.data.page.PageLink;
 | 
			
		||||
import org.thingsboard.server.common.data.security.UserCredentials;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent;
 | 
			
		||||
import org.thingsboard.server.dao.entity.AbstractEntityService;
 | 
			
		||||
import org.thingsboard.server.dao.exception.IncorrectParameterException;
 | 
			
		||||
import org.thingsboard.server.dao.service.DataValidator;
 | 
			
		||||
@ -211,7 +212,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
 | 
			
		||||
        userAuthSettingsDao.removeByUserId(userId);
 | 
			
		||||
        deleteEntityRelations(tenantId, userId);
 | 
			
		||||
        userDao.removeById(tenantId, userId.getId());
 | 
			
		||||
        eventPublisher.publishEvent(new UserAuthDataChangedEvent(userId, null, true));
 | 
			
		||||
        eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(userId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user