package com.saltedhashed; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.inject.Inject; import org.joda.time.DateTimeConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import com.google.common.base.Joiner; import com.saltedhashed.dao.PageableOperation; import com.saltedhashed.dao.SiteDao; import com.saltedhashed.model.PasswordRequest; import com.saltedhashed.model.PasswordResponse; import com.saltedhashed.model.Site; import com.saltedhashed.model.SiteStatus; @Component public class SiteVerifierJob { private static final Logger logger = LoggerFactory.getLogger(SiteVerifierJob.class); @Inject private SiteDao dao; private RestTemplate restTemplate = new RestTemplate(); private Verifier verifier = new Verifier(); private Joiner joiner = Joiner.on('\n'); @Scheduled(fixedDelay=DateTimeConstants.MILLIS_PER_DAY) public void run() { final List<PasswordRequest> requests = generateTestPasswordRequests(); dao.performBatched(200, new PageableOperation<Site>() { @Override public void execute() { List<Site> sites = getData(); for (Site site : sites) { try { verifySite(requests, site); } catch (Exception ex) { logger.error("Problem verifying site " + site.getBaseUrl(), ex); } } } }); } public List<PasswordRequest> generateTestPasswordRequests() { final List<PasswordRequest> requests = new ArrayList<>(3); for (int i = 0; i < 3; i ++) { PasswordRequest request = new PasswordRequest(); request.setPassword(PasswordUtils.getRandomPassword()); requests.add(request); } return requests; } public void verifySite(final List<PasswordRequest> requests, Site site) { SiteStatus status = new SiteStatus(); status.setHttpCode(200); Set<String> messages = new HashSet<>(); boolean success = true; for (PasswordRequest request : requests) { try { PasswordResponse response = restTemplate.postForObject(site.getBaseUrl() + site.getEndpointPath(), request, PasswordResponse.class); boolean verificationResult = verifier.verify(request.getPassword(), response); if (!verificationResult) { messages.add("Incorrect hash for password " + request.getPassword()+ ", using algorithm " + response.getAlgorithm() + "."); } success = success && verificationResult; } catch (HttpClientErrorException ex) { success = false; status.setHttpCode(ex.getStatusCode().value()); messages.add(ex.getStatusText()); } catch (RestClientException ex) { success = false; messages.add("REST exception: " + ex.getMessage()); } catch (Exception ex) { success = false; messages.add("Unexpected problem."); logger.warn("Problem with site: " + site, ex); } } status.setSuccess(success); status.setMessage(joiner.join(messages)); status.setTimestamp(System.currentTimeMillis()); site.getStatuses().add(0, status); if (site.getStatuses().size() > 5) { site.getStatuses().remove(5); } dao.save(site); } }