package org.apereo.cas.otp.repository.token;
import com.google.common.cache.LoadingCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
/**
* This is {@link CachingOneTimeTokenRepository}.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
public class CachingOneTimeTokenRepository extends BaseOneTimeTokenRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(CachingOneTimeTokenRepository.class);
private final LoadingCache<String, Collection<OneTimeToken>> storage;
public CachingOneTimeTokenRepository(final LoadingCache<String, Collection<OneTimeToken>> storage) {
this.storage = storage;
}
@Override
public void cleanInternal() {
LOGGER.debug("Beginning to clean up the cache storage to remove expiring tokens");
this.storage.cleanUp();
LOGGER.debug("Total of [{}] token(s) remain in the cache and may be removed in future iterations", this.storage.size());
}
@Override
public void store(final OneTimeToken token) {
if (exists(token.getUserId(), token.getToken())) {
try {
final Collection<OneTimeToken> tokens = this.storage.get(token.getUserId());
tokens.add(token);
LOGGER.debug("Storing previously used tokens [{}] for user [{}]", tokens, token.getUserId());
this.storage.put(token.getUserId(), tokens);
} catch (final Exception e) {
LOGGER.warn(e.getMessage(), e);
}
} else {
final Collection<OneTimeToken> tokens = new ArrayList<>();
tokens.add(token);
LOGGER.debug("Storing previously used token [{}] for user [{}]", token, token.getUserId());
this.storage.put(token.getUserId(), tokens);
}
}
@Override
public boolean exists(final String uid, final Integer otp) {
try {
final Collection<OneTimeToken> tokens = this.storage.getIfPresent(uid);
LOGGER.debug("Found used tokens [{}]", tokens);
return tokens != null && tokens.stream().anyMatch(t -> t.getToken().equals(otp));
} catch (final Exception e) {
LOGGER.warn(e.getMessage(), e);
}
return false;
}
}