Merge pull request #5 from myrle-krantz/develop

Various changes to support key rotation with keys designated by timestamps.
diff --git a/src/main/java/io/mifos/core/test/domain/DateStampChecker.java b/src/main/java/io/mifos/core/test/domain/DateStampChecker.java
new file mode 100644
index 0000000..936035e
--- /dev/null
+++ b/src/main/java/io/mifos/core/test/domain/DateStampChecker.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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 io.mifos.core.test.domain;
+
+import io.mifos.core.lang.DateConverter;
+import org.junit.Assert;
+
+import java.time.Clock;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+
+/**
+ * Support class for testing that the correct time stamp is returned
+ *
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("WeakerAccess")
+public class DateStampChecker {
+  private final LocalDate expectedDateStamp;
+  private final int maximumDelta;
+
+  public static DateStampChecker inTheFuture(final int offset)
+  {
+    return new DateStampChecker(LocalDate.now(Clock.systemUTC()).plusDays(offset), 0);
+  }
+
+  private DateStampChecker(final LocalDate expectedDateStamp, final int maximumDelta) {
+    this.expectedDateStamp = expectedDateStamp;
+    this.maximumDelta = maximumDelta;
+  }
+
+  public void assertCorrect(final String dateStamp)
+  {
+    Assert.assertTrue("Delta from expected should have been less than " +
+                    maximumDelta + ". Timestamp string was " + dateStamp + ".",
+            isCorrect(dateStamp));
+  }
+
+  public boolean isCorrect(final String dateStamp) {
+    final LocalDate parsedDateStamp = DateConverter.dateFromIsoString(dateStamp);
+
+    final long deltaFromExpected = parsedDateStamp.until(expectedDateStamp, ChronoUnit.DAYS);
+
+    return deltaFromExpected <= maximumDelta;
+  }
+}
diff --git a/src/main/java/io/mifos/core/test/env/TestEnvironment.java b/src/main/java/io/mifos/core/test/env/TestEnvironment.java
index 0d4e079..284f3ee 100644
--- a/src/main/java/io/mifos/core/test/env/TestEnvironment.java
+++ b/src/main/java/io/mifos/core/test/env/TestEnvironment.java
@@ -35,6 +35,7 @@
 
   public static final String SERVER_CONTEXT_PATH_PROPERTY = "server.contextPath";
 
+  public static final String SYSTEM_PUBLIC_KEY_TIMESTAMP_PROPERTY = "system.publicKey.timestamp";
   public static final String SYSTEM_PUBLIC_KEY_MODULUS_PROPERTY = "system.publicKey.modulus";
   public static final String SYSTEM_PUBLIC_KEY_EXPONENT_PROPERTY = "system.publicKey.exponent";
   public static final String SYSTEM_PRIVATE_KEY_MODULUS_PROPERTY = "system.privateKey.modulus";
@@ -137,6 +138,10 @@
         this.properties.getProperty(TestEnvironment.SERVER_CONTEXT_PATH_PROPERTY);
   }
 
+  public String getSystemKeyTimestamp() {
+    return keyPairHolder.getTimestamp();
+  }
+
   public RSAPublicKey getSystemPublicKey() {
     return keyPairHolder.publicKey();
   }
@@ -145,16 +150,18 @@
     return keyPairHolder.privateKey();
   }
 
-  public void setKeyPair(final RSAPublicKey publicKey, final RSAPrivateKey privateKey)
+  public void setKeyPair(final String timestamp, final RSAPublicKey publicKey, final RSAPrivateKey privateKey)
   {
-    this.keyPairHolder = new RsaKeyPairFactory.KeyPairHolder(publicKey, privateKey);
+    this.keyPairHolder = new RsaKeyPairFactory.KeyPairHolder(timestamp, publicKey, privateKey);
 
+    this.properties.setProperty(SYSTEM_PUBLIC_KEY_TIMESTAMP_PROPERTY, getSystemKeyTimestamp());
     this.properties.setProperty(SYSTEM_PUBLIC_KEY_MODULUS_PROPERTY, publicKey.getModulus().toString());
     this.properties.setProperty(SYSTEM_PUBLIC_KEY_EXPONENT_PROPERTY, publicKey.getPublicExponent().toString());
   }
 
   public void addSystemPrivateKeyToProperties()
   {
+    setProperty(SYSTEM_PUBLIC_KEY_TIMESTAMP_PROPERTY, getSystemKeyTimestamp());
     setProperty(SYSTEM_PRIVATE_KEY_MODULUS_PROPERTY, getSystemPrivateKey().getModulus().toString());
     setProperty(SYSTEM_PRIVATE_KEY_EXPONENT_PROPERTY, getSystemPrivateKey().getPrivateExponent().toString());
   }
@@ -205,6 +212,7 @@
 
     this.keyPairHolder = RsaKeyPairFactory.createKeyPair();
 
+    this.properties.setProperty(SYSTEM_PUBLIC_KEY_TIMESTAMP_PROPERTY, this.keyPairHolder.getTimestamp());
     this.properties.setProperty(SYSTEM_PUBLIC_KEY_MODULUS_PROPERTY, this.keyPairHolder.publicKey().getModulus().toString());
     this.properties.setProperty(SYSTEM_PUBLIC_KEY_EXPONENT_PROPERTY, this.keyPairHolder.publicKey().getPublicExponent().toString());
   }
diff --git a/src/test/java/io/mifos/core/test/domain/DateStampCheckerTest.java b/src/test/java/io/mifos/core/test/domain/DateStampCheckerTest.java
new file mode 100644
index 0000000..743666e
--- /dev/null
+++ b/src/test/java/io/mifos/core/test/domain/DateStampCheckerTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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 io.mifos.core.test.domain;
+
+import io.mifos.core.lang.DateConverter;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.time.Clock;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+
+/**
+ *
+ * @author Myrle Krantz
+ */
+public class DateStampCheckerTest {
+  @Test
+  public void inTheFuture() throws Exception {
+    final DateStampChecker checker = DateStampChecker.inTheFuture(5);
+    final LocalDate now = LocalDate.now(Clock.systemUTC());
+    final LocalDate fiveDaysFromNow = now.plus(5, ChronoUnit.DAYS);
+    final String fiveDaysFromNowAsString = DateConverter.toIsoString(fiveDaysFromNow);
+    checker.assertCorrect(fiveDaysFromNowAsString);
+
+    final String nowAsString = DateConverter.toIsoString(now);
+    Assert.assertFalse(checker.isCorrect(nowAsString));
+
+  }
+}