Skip to content

Commit 27e005b

Browse files
committed
More refactoring and fixing tests
1 parent b7656ba commit 27e005b

File tree

9 files changed

+333
-288
lines changed

9 files changed

+333
-288
lines changed

src/main/java/com/uid2/admin/Main.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.uid2.admin.legacy.RotatingLegacyClientKeyProvider;
1515
import com.uid2.admin.managers.KeysetManager;
1616
import com.uid2.admin.monitoring.DataStoreMetrics;
17+
import com.uid2.admin.salt.SaltRotation;
1718
import com.uid2.admin.secret.*;
1819
import com.uid2.admin.store.*;
1920
import com.uid2.admin.store.reader.RotatingAdminKeysetStore;

src/main/java/com/uid2/admin/secret/SaltRotation.java renamed to src/main/java/com/uid2/admin/salt/SaltRotation.java

Lines changed: 20 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.uid2.admin.secret;
1+
package com.uid2.admin.salt;
22

33
import com.uid2.admin.AdminConst;
44
import com.uid2.shared.model.SaltEntry;
@@ -10,11 +10,7 @@
1010
import org.slf4j.Logger;
1111
import org.slf4j.LoggerFactory;
1212

13-
import java.time.Duration;
14-
import java.time.Instant;
15-
import java.time.LocalDate;
16-
import java.time.ZoneOffset;
17-
import java.time.format.DateTimeFormatter;
13+
import java.time.*;
1814
import java.time.temporal.ChronoUnit;
1915
import java.util.*;
2016
import java.util.stream.Collectors;
@@ -60,9 +56,9 @@ public Result rotateSalts(
6056

6157
var postRotationSalts = rotateSalts(preRotationSalts, saltsToRotate, targetDate);
6258

63-
logSaltAgeCounts("rotatable-salts", targetDate, rotatableSalts);
64-
logSaltAgeCounts("rotated-salts", targetDate, saltsToRotate);
65-
logSaltAgeCounts("total-salts", targetDate, Arrays.asList(postRotationSalts));
59+
logSaltAges("rotatable-salts", targetDate, rotatableSalts);
60+
logSaltAges("rotated-salts", targetDate, saltsToRotate);
61+
logSaltAges("total-salts", targetDate, Arrays.asList(postRotationSalts));
6662

6763
var nextSnapshot = new SaltSnapshot(
6864
nextEffective,
@@ -118,15 +114,15 @@ private SaltEntry updateSalt(SaltEntry oldSalt, TargetDate targetDate, boolean s
118114
}
119115

120116
private long calculateRefreshFrom(SaltEntry salt, TargetDate targetDate) {
121-
long multiplier = targetDate.ageOfSaltInMs(salt) / THIRTY_DAYS_IN_MS + 1;
117+
long multiplier = targetDate.saltAgeInDays(salt) / 30 + 1;
122118
return salt.lastUpdated() + (multiplier * THIRTY_DAYS_IN_MS);
123119
}
124120

125121
private String calculatePreviousSalt(SaltEntry salt, boolean shouldRotate, TargetDate targetDate) {
126122
if (shouldRotate) {
127123
return salt.currentSalt();
128124
}
129-
if (targetDate.ageOfSaltInDays(salt) < 90) {
125+
if (targetDate.saltAgeInDays(salt) < 90) {
130126
return salt.previousSalt();
131127
}
132128
return null;
@@ -167,88 +163,38 @@ private List<SaltEntry> pickSaltsToRotateInTimeWindow(
167163
long minLastUpdated,
168164
long maxLastUpdated
169165
) {
170-
var candidateSalts = new ArrayList<SaltEntry>();
171-
for (SaltEntry salt : rotatableSalts) {
172-
var lastUpdated = salt.lastUpdated();
173-
var isInTimeWindow = minLastUpdated <= lastUpdated && lastUpdated < maxLastUpdated;
174-
175-
if (isInTimeWindow) {
176-
candidateSalts.add(salt);
177-
}
178-
}
166+
ArrayList<SaltEntry> candidateSalts = rotatableSalts.stream()
167+
.filter(salt -> minLastUpdated <= salt.lastUpdated() && salt.lastUpdated() < maxLastUpdated)
168+
.collect(Collectors.toCollection(ArrayList::new));
179169

180170
if (candidateSalts.size() <= maxIndexes) {
181171
return candidateSalts;
182172
}
183173

184174
Collections.shuffle(candidateSalts);
185-
return candidateSalts.subList(0, Math.min(maxIndexes, candidateSalts.size()));
175+
176+
return candidateSalts.stream().limit(maxIndexes).collect(Collectors.toList());
186177
}
187178

188-
private void logSaltAgeCounts(String saltCountType, TargetDate targetDate, Collection<SaltEntry> salts) {
179+
private void logSaltAges(String saltCountType, TargetDate targetDate, Collection<SaltEntry> salts) {
189180
var ages = new HashMap<Long, Long>(); // salt age to count
190181
for (var salt : salts) {
191-
long ageInDays = targetDate.ageOfSaltInDays(salt);
182+
long ageInDays = targetDate.saltAgeInDays(salt);
192183
ages.put(ageInDays, ages.getOrDefault(ageInDays, 0L) + 1);
193184
}
194185

195186
for (var entry : ages.entrySet()) {
196-
LOGGER.info("salt-count-type={} target-date={} age={} salt-count={}", saltCountType, targetDate, entry.getKey(), entry.getValue());
197-
}
198-
}
199-
200-
public static class TargetDate {
201-
private final static long DAY_IN_MS = Duration.ofDays(1).toMillis();
202-
203-
private final LocalDate date;
204-
private final long epochMs;
205-
private final Instant instant;
206-
private final String formatted;
207-
208-
public TargetDate(LocalDate date) {
209-
this.instant = date.atStartOfDay().toInstant(ZoneOffset.UTC);
210-
this.date = date;
211-
this.epochMs = instant.toEpochMilli();
212-
this.formatted = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
213-
}
214-
215-
public static TargetDate of(int year, int month, int day) {
216-
return new TargetDate(LocalDate.of(year, month, day));
217-
}
218-
219-
public long asEpochMs() {
220-
return epochMs;
221-
}
222-
223-
public Instant asInstant() {
224-
return instant;
225-
}
226-
227-
public long ageOfSaltInMs(SaltEntry salt) {
228-
return this.asEpochMs() - salt.lastUpdated();
229-
}
230-
231-
public long ageOfSaltInDays(SaltEntry salt) {
232-
return ageOfSaltInMs(salt) / DAY_IN_MS;
233-
}
234-
235-
public TargetDate plusDays(int days) {
236-
return new TargetDate(date.plusDays(days));
237-
}
238-
239-
public TargetDate minusDays(int days) {
240-
return new TargetDate(date.minusDays(days));
241-
}
242-
243-
@Override
244-
public String toString() {
245-
return formatted;
187+
LOGGER.info("salt-count-type={} target-date={} age={} salt-count={}",
188+
saltCountType,
189+
targetDate,
190+
entry.getKey(),
191+
entry.getValue()
192+
);
246193
}
247194
}
248195

249196
@Getter
250197
public static class Result {
251-
252198
private final SaltSnapshot snapshot; // can be null if new snapshot is not needed
253199
private final String reason; // why you are not getting a new snapshot
254200

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.uid2.admin.salt;
2+
3+
import com.uid2.shared.model.SaltEntry;
4+
5+
import java.time.*;
6+
import java.time.format.DateTimeFormatter;
7+
import java.util.Objects;
8+
9+
public class TargetDate {
10+
private final static long DAY_IN_MS = Duration.ofDays(1).toMillis();
11+
12+
private final LocalDate date;
13+
private final long epochMs;
14+
private final Instant instant;
15+
private final String formatted;
16+
17+
public TargetDate(LocalDate date) {
18+
this.instant = date.atStartOfDay().toInstant(ZoneOffset.UTC);
19+
this.date = date;
20+
this.epochMs = instant.toEpochMilli();
21+
this.formatted = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
22+
}
23+
24+
public static TargetDate now() {
25+
return new TargetDate(LocalDate.now(Clock.systemUTC()));
26+
}
27+
28+
public static TargetDate of(int year, int month, int day) {
29+
return new TargetDate(LocalDate.of(year, month, day));
30+
}
31+
32+
public long asEpochMs() {
33+
return epochMs;
34+
}
35+
36+
public Instant asInstant() {
37+
return instant;
38+
}
39+
40+
// relative to this date
41+
public long saltAgeInDays(SaltEntry salt) {
42+
return (this.asEpochMs() - salt.lastUpdated()) / DAY_IN_MS;
43+
}
44+
45+
public TargetDate plusDays(int days) {
46+
return new TargetDate(date.plusDays(days));
47+
}
48+
49+
public TargetDate minusDays(int days) {
50+
return new TargetDate(date.minusDays(days));
51+
}
52+
53+
@Override
54+
public String toString() {
55+
return formatted;
56+
}
57+
58+
@Override
59+
public boolean equals(Object o) {
60+
if (o == null || getClass() != o.getClass()) return false;
61+
TargetDate that = (TargetDate) o;
62+
return epochMs == that.epochMs;
63+
}
64+
65+
@Override
66+
public int hashCode() {
67+
return Objects.hashCode(epochMs);
68+
}
69+
}

src/main/java/com/uid2/admin/vertx/service/SaltService.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package com.uid2.admin.vertx.service;
22

33
import com.uid2.admin.auth.AdminAuthMiddleware;
4-
import com.uid2.admin.secret.SaltRotation;
4+
import com.uid2.admin.salt.SaltRotation;
5+
import com.uid2.admin.salt.TargetDate;
56
import com.uid2.admin.store.writer.SaltStoreWriter;
67
import com.uid2.admin.vertx.RequestUtil;
78
import com.uid2.admin.vertx.ResponseUtil;
@@ -74,13 +75,16 @@ private void handleSaltSnapshots(RoutingContext rc) {
7475
private void handleSaltRotate(RoutingContext rc) {
7576
try {
7677
final Optional<Double> fraction = RequestUtil.getDouble(rc, "fraction");
77-
if (!fraction.isPresent()) return;
78+
if (fraction.isEmpty()) return;
7879
final Duration[] minAges = RequestUtil.getDurations(rc, "min_ages_in_seconds");
7980
if (minAges == null) return;
80-
final SaltRotation.TargetDate targetDate = new SaltRotation.TargetDate(
81+
82+
83+
final TargetDate targetDate =
8184
RequestUtil.getDate(rc, "target_date", DateTimeFormatter.ISO_LOCAL_DATE)
82-
.orElse(LocalDate.now(Clock.systemUTC()).plusDays(1))
83-
);
85+
.map(TargetDate::new)
86+
.orElse(TargetDate.now().plusDays(1))
87+
;
8488

8589
// force refresh
8690
this.saltProvider.loadContent();
@@ -91,8 +95,7 @@ private void handleSaltRotate(RoutingContext rc) {
9195
final List<RotatingSaltProvider.SaltSnapshot> snapshots = this.saltProvider.getSnapshots();
9296
final RotatingSaltProvider.SaltSnapshot lastSnapshot = snapshots.getLast();
9397

94-
final SaltRotation.Result result = saltRotation.rotateSalts(
95-
lastSnapshot, minAges, fraction.get(), targetDate);
98+
final SaltRotation.Result result = saltRotation.rotateSalts(lastSnapshot, minAges, fraction.get(), targetDate);
9699
if (!result.hasSnapshot()) {
97100
ResponseUtil.error(rc, 200, result.getReason());
98101
return;

0 commit comments

Comments
 (0)