Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Java] safe id generator #213

Merged
merged 4 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ly.count.sdk.java.internal;

import javax.annotation.Nonnull;

public interface IdGenerator {
@Nonnull String generateId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class InternalConfig extends Config {
ImmediateRequestGenerator immediateRequestGenerator = null;
public SDKCore sdk;
public StorageProvider storageProvider;
protected IdGenerator viewIdGenerator;
protected IdGenerator eventIdGenerator;

/**
* Shouldn't be used!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,15 @@ public void init(final InternalConfig givenConfig) {
setDeviceIdFromStorageIfExist(config);

requestQueueMemory = new ArrayDeque<>(config.getRequestQueueMaxSize());

if (config.viewIdGenerator == null) {
config.viewIdGenerator = Utils::safeRandomVal;
}

if (config.eventIdGenerator == null) {
config.eventIdGenerator = Utils::safeRandomVal;
}

// ModuleSessions is always enabled, even without consent
int consents = config.getFeatures1() | CoreFeature.Sessions.getIndex();
// build modules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static Instant getCurrentInstant() {
return getCurrentInstant(timestampMs());
}

private static Instant getCurrentInstant(long timestamp) {
protected static Instant getCurrentInstant(long timestamp) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
return new Instant(timestamp,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ly.count.sdk.java.internal;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class ScenarioUtilsTests {

/**
* "safeRandomVal"
* ### 001_validatingIDGenerator
* <p>
* testing the ID generator function that is used for events and views
* <p>
* Generate 2 values
* <p>
* they should be different.
* They should be 21 chars long.
* They should contain on base64 characters. first 8 one is base64 string and last 13 one is timestamp
*
* @throws NumberFormatException for parsing part 2
*/
@Test
public void _001_validatingIDGenerator() throws NumberFormatException {
String val1 = Utils.safeRandomVal();
String val2 = Utils.safeRandomVal();

Assert.assertNotEquals(val2, val1);

TestUtils.validateSafeRandomVal(val1);
TestUtils.validateSafeRandomVal(val2);
}
}
30 changes: 30 additions & 0 deletions sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import ly.count.sdk.java.Config;
import ly.count.sdk.java.Countly;
Expand Down Expand Up @@ -586,4 +588,32 @@ protected static Map<String, Object> map(Map<String, Object> gonnaAddMap, Object
}
return map;
}

/**
* Validates a random generated safe value,
* Value length should be 21
* Value should contain a timestamp at the end
* Value should be base64 encoded and first 8 should be it
*
* @param val
*/
static void validateSafeRandomVal(String val) {
Assert.assertEquals(21, val.length());

Pattern base64Pattern = Pattern.compile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$");

String timestampStr = val.substring(val.length() - 13);
String base64Str = val.substring(0, val.length() - 13);

Matcher matcher = base64Pattern.matcher(base64Str);
if (matcher.matches()) {
TimeUtils.Instant instant = TimeUtils.getCurrentInstant(Long.parseLong(timestampStr));
Assert.assertTrue(instant.dow >= 0 && instant.dow < 7);
Assert.assertTrue(instant.hour >= 0 && instant.hour < 24);
Assert.assertTrue(instant.timestamp > 0);
Assert.assertTrue(instant.tz >= -720 && instant.tz <= 840);
} else {
Assert.fail("No match for " + val);
}
}
}
25 changes: 0 additions & 25 deletions sdk-java/src/test/java/ly/count/sdk/java/internal/UtilsTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ly.count.sdk.java.Config;
import org.junit.Assert;
import org.junit.Before;
Expand Down Expand Up @@ -561,27 +559,4 @@ public void readStream() {
Assert.assertNull(Utils.readStream(null, logger));
Assert.assertEquals(value, new String(Utils.readStream(new ByteArrayInputStream(value.getBytes()), logger)));
}

/**
* "safeRandomVal"
* An random value is generated and validated by the base64 regex, and consist of 2 parts
* Should return the string value generated by the algorithm and matches with the regex
*
* @throws NumberFormatException for parsing part 2
*/
@Test
public void safeRandomVal() throws NumberFormatException {
String val = Utils.safeRandomVal();
Pattern base64Pattern = Pattern.compile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$");

String timestampStr = val.substring(val.length() - 13);
String base64Str = val.substring(0, val.length() - 13);

Matcher matcher = base64Pattern.matcher(base64Str);
if (matcher.matches()) {
Assert.assertTrue(Long.parseLong(timestampStr) > 0);
} else {
Assert.fail("No match for " + val);
}
}
}