|
16 | 16 |
|
17 | 17 | import static java.util.stream.Collectors.toList; |
18 | 18 |
|
19 | | -public class SaltRotation implements ISaltRotation { |
| 19 | +public class SaltRotation { |
20 | 20 | private final IKeyGenerator keyGenerator; |
| 21 | + private final long THIRTY_DAYS_IN_MS = Duration.ofDays(30).toMillis(); |
21 | 22 |
|
22 | 23 | public SaltRotation(IKeyGenerator keyGenerator) { |
23 | 24 | this.keyGenerator = keyGenerator; |
24 | 25 | } |
25 | 26 |
|
26 | | - @Override |
27 | 27 | public Result rotateSalts(RotatingSaltProvider.SaltSnapshot lastSnapshot, |
28 | 28 | Duration[] minAges, |
29 | 29 | double fraction, |
30 | 30 | LocalDate targetDate) throws Exception { |
31 | | - |
32 | 31 | final Instant nextEffective = targetDate.atStartOfDay().toInstant(ZoneOffset.UTC); |
33 | 32 | final Instant nextExpires = nextEffective.plus(7, ChronoUnit.DAYS); |
34 | 33 | if (nextEffective.equals(lastSnapshot.getEffective()) || nextEffective.isBefore(lastSnapshot.getEffective())) { |
@@ -63,19 +62,26 @@ private SaltEntry[] updateSalts(SaltEntry[] oldSalts, List<Integer> saltIndexesT |
63 | 62 | private SaltEntry updateSalt(SaltEntry oldSalt, boolean shouldRotate, long nextEffective) throws Exception { |
64 | 63 | var currentSalt = shouldRotate ? this.keyGenerator.generateRandomKeyString(32) : oldSalt.currentSalt(); |
65 | 64 | var lastUpdated = shouldRotate ? nextEffective : oldSalt.lastUpdated(); |
| 65 | + var refreshFrom = calculateRefreshFrom(oldSalt.lastUpdated(), nextEffective); |
66 | 66 |
|
67 | 67 | return new SaltEntry( |
68 | 68 | oldSalt.id(), |
69 | 69 | oldSalt.hashedId(), |
70 | 70 | lastUpdated, |
71 | 71 | currentSalt, |
72 | | - null, |
| 72 | + refreshFrom, |
73 | 73 | null, |
74 | 74 | null, |
75 | 75 | null |
76 | 76 | ); |
77 | 77 | } |
78 | 78 |
|
| 79 | + private long calculateRefreshFrom(long lastUpdated, long nextEffective) { |
| 80 | + long age = nextEffective - lastUpdated; |
| 81 | + long multiplier = age / THIRTY_DAYS_IN_MS + 1; |
| 82 | + return lastUpdated + (multiplier * THIRTY_DAYS_IN_MS); |
| 83 | + } |
| 84 | + |
79 | 85 | private List<Integer> pickSaltIndexesToRotate( |
80 | 86 | SaltSnapshot lastSnapshot, |
81 | 87 | Instant nextEffective, |
@@ -125,4 +131,24 @@ private static boolean isBetween(long t, long minInclusive, long maxExclusive) { |
125 | 131 | return minInclusive <= t && t < maxExclusive; |
126 | 132 | } |
127 | 133 |
|
| 134 | + public static class Result { |
| 135 | + private final RotatingSaltProvider.SaltSnapshot snapshot; // can be null if new snapshot is not needed |
| 136 | + private final String reason; // why you are not getting a new snapshot |
| 137 | + |
| 138 | + private Result(RotatingSaltProvider.SaltSnapshot snapshot, String reason) { |
| 139 | + this.snapshot = snapshot; |
| 140 | + this.reason = reason; |
| 141 | + } |
| 142 | + |
| 143 | + public boolean hasSnapshot() { return snapshot != null; } |
| 144 | + public RotatingSaltProvider.SaltSnapshot getSnapshot() { return snapshot; } |
| 145 | + public String getReason() { return reason; } |
| 146 | + |
| 147 | + public static Result fromSnapshot(RotatingSaltProvider.SaltSnapshot snapshot) { |
| 148 | + return new Result(snapshot, null); |
| 149 | + } |
| 150 | + public static Result noSnapshot(String reason) { |
| 151 | + return new Result(null, reason); |
| 152 | + } |
| 153 | + } |
128 | 154 | } |
0 commit comments