package org.apereo.cas.otp.repository.credentials;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.util.serialization.AbstractJacksonBackedStringSerializer;
import org.apereo.cas.util.serialization.StringSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import java.util.Collection;
import java.util.List;
import java.util.TreeSet;
/**
* This is {@link BaseJsonOneTimeTokenCredentialRepository}.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
public abstract class BaseJsonOneTimeTokenCredentialRepository extends BaseOneTimeTokenCredentialRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(BaseJsonOneTimeTokenCredentialRepository.class);
private final Resource location;
private final StringSerializer<TreeSet<OneTimeTokenAccount>> serializer = new OneTimeAccountSerializer();
public BaseJsonOneTimeTokenCredentialRepository(final Resource location) {
this.location = location;
}
@Override
public String getSecret(final String username) {
try {
if (!this.location.getFile().exists()) {
LOGGER.warn("JSON account repository file [{}] is not found.", this.location.getFile());
return null;
}
if (this.location.getFile().length() <= 0) {
LOGGER.warn("JSON account repository file [{}] is empty.", this.location.getFile());
return null;
}
final Collection<OneTimeTokenAccount> c = this.serializer.from(this.location.getFile());
return c.stream()
.filter(a -> StringUtils.isNotBlank(a.getUsername()) && a.getUsername().equals(username))
.map(OneTimeTokenAccount::getSecretKey)
.findAny()
.orElse(null);
} catch (final Exception e) {
LOGGER.error(e.getMessage(), e);
}
return null;
}
@Override
public void save(final String userName, final String secretKey,
final int validationCode,
final List<Integer> scratchCodes) {
try {
LOGGER.debug("Storing google authenticator account for [{}]", userName);
final OneTimeTokenAccount account = new OneTimeTokenAccount(userName, secretKey, validationCode, scratchCodes);
LOGGER.debug("Ensuring JSON repository file exists at [{}]", this.location.getFile());
this.location.getFile().createNewFile();
final TreeSet<OneTimeTokenAccount> c;
if (this.location.getFile().length() > 0) {
LOGGER.debug("Reading JSON repository file at [{}]", this.location.getFile());
c = this.serializer.from(this.location.getFile());
} else {
c = new TreeSet<>();
}
LOGGER.debug("Found [{}] account(s) and added google authenticator account for [{}]", c.size(), userName);
c.add(account);
LOGGER.debug("Saving google authenticator accounts back to the JSON file at [{}]", this.location.getFile());
this.serializer.to(this.location.getFile(), c);
} catch (final Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
private static class OneTimeAccountSerializer extends AbstractJacksonBackedStringSerializer<TreeSet<OneTimeTokenAccount>> {
private static final long serialVersionUID = 1466569521275630254L;
@Override
protected Class getTypeToSerialize() {
return TreeSet.class;
}
}
}