add toke cleanup
This commit is contained in:
@@ -2,9 +2,29 @@ package com.ddf.vodsystem.repositories;
|
|||||||
|
|
||||||
import com.ddf.vodsystem.entities.TokenFamily;
|
import com.ddf.vodsystem.entities.TokenFamily;
|
||||||
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.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface TokenFamilyRepository extends JpaRepository<TokenFamily, Long> {
|
public interface TokenFamilyRepository extends JpaRepository<TokenFamily, Long> {
|
||||||
|
/**
|
||||||
|
* Deletes families that can no longer be refreshed: revoked, expired, or with every refresh
|
||||||
|
* token expired. Their refresh tokens are removed by the {@code ON DELETE CASCADE} foreign key.
|
||||||
|
*
|
||||||
|
* @return the number of families deleted
|
||||||
|
*/
|
||||||
|
@Modifying
|
||||||
|
@Query("""
|
||||||
|
DELETE FROM TokenFamily f
|
||||||
|
WHERE f.revokedAt IS NOT NULL
|
||||||
|
OR f.expiresAt <= ?1
|
||||||
|
OR NOT EXISTS (
|
||||||
|
SELECT 1 FROM RefreshToken r
|
||||||
|
WHERE r.tokenFamily = f AND r.expiresAt > ?1
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
int deleteDead(Instant now);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import com.ddf.vodsystem.entities.User;
|
|||||||
import com.ddf.vodsystem.exceptions.NotAuthenticated;
|
import com.ddf.vodsystem.exceptions.NotAuthenticated;
|
||||||
import com.ddf.vodsystem.repositories.RefreshTokenRepository;
|
import com.ddf.vodsystem.repositories.RefreshTokenRepository;
|
||||||
import com.ddf.vodsystem.repositories.TokenFamilyRepository;
|
import com.ddf.vodsystem.repositories.TokenFamilyRepository;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -28,6 +31,7 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class TokenService {
|
public class TokenService {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TokenService.class);
|
||||||
private static final SecureRandom RNG = new SecureRandom();
|
private static final SecureRandom RNG = new SecureRandom();
|
||||||
private static final HexFormat HEX = HexFormat.of();
|
private static final HexFormat HEX = HexFormat.of();
|
||||||
|
|
||||||
@@ -192,6 +196,19 @@ public class TokenService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scheduled cleanup that deletes token families that can no longer be refreshed, along with all
|
||||||
|
* their refresh tokens.
|
||||||
|
* <p>
|
||||||
|
* Runs hourly. Used tokens in live families are kept, since reuse detection needs them.
|
||||||
|
*/
|
||||||
|
@Scheduled(fixedDelay = 3_600_000)
|
||||||
|
@Transactional
|
||||||
|
public void deleteDeadSessions() {
|
||||||
|
int deleted = tokenFamilyRepository.deleteDead(Instant.now(clock));
|
||||||
|
if (deleted > 0) logger.info("Deleted {} dead token families", deleted);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result of a successful {@link #rotate(String)}.
|
* Result of a successful {@link #rotate(String)}.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user