Skip to content

Commit cd5f970

Browse files
feat: Handle hashed email for rokt (#599)
1 parent 0d7e62e commit cd5f970

2 files changed

Lines changed: 618 additions & 343 deletions

File tree

android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java

Lines changed: 87 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,50 +1364,51 @@ public void execute(@NonNull String viewName,
13641364
}
13651365
MParticle instance = MParticle.getInstance();
13661366
MParticleUser user = instance.Identity().getCurrentUser();
1367-
String email = attributes.get("email");
1367+
String email = getValueIgnoreCase(attributes, "email");
1368+
String hashedEmail = getValueIgnoreCase(attributes, "emailsha256");
13681369
Map<String, String> finalAttributes = attributes;
1369-
confirmEmail(email,user,instance.Identity(), () -> {
1370-
JSONArray jsonArray = new JSONArray();
1371-
1372-
KitConfiguration kitConfig = provider.getConfiguration();
1373-
if (kitConfig != null) {
1374-
try {
1375-
jsonArray = kitConfig.getPlacementAttributesMapping();
1376-
} catch (JSONException e) {
1377-
Logger.warning("Invalid placementAttributes for kit: " + provider.getName() + " JSON: " + e.getMessage());
1370+
confirmEmail(email, hashedEmail, user, instance.Identity(), () -> {
1371+
JSONArray jsonArray = new JSONArray();
1372+
1373+
KitConfiguration kitConfig = provider.getConfiguration();
1374+
if (kitConfig != null) {
1375+
try {
1376+
jsonArray = kitConfig.getPlacementAttributesMapping();
1377+
} catch (JSONException e) {
1378+
Logger.warning("Invalid placementAttributes for kit: " + provider.getName() + " JSON: " + e.getMessage());
1379+
}
13781380
}
1379-
}
1380-
for (int i = 0; i < jsonArray.length(); i++) {
1381-
JSONObject obj = jsonArray.optJSONObject(i);
1382-
if (obj == null) continue;
1383-
String mapFrom = obj.optString("map");
1384-
String mapTo = obj.optString("value");
1385-
if (finalAttributes.containsKey(mapFrom)) {
1386-
String value = finalAttributes.remove(mapFrom);
1387-
finalAttributes.put(mapTo, value);
1381+
for (int i = 0; i < jsonArray.length(); i++) {
1382+
JSONObject obj = jsonArray.optJSONObject(i);
1383+
if (obj == null) continue;
1384+
String mapFrom = obj.optString("map");
1385+
String mapTo = obj.optString("value");
1386+
if (finalAttributes.containsKey(mapFrom)) {
1387+
String value = finalAttributes.remove(mapFrom);
1388+
finalAttributes.put(mapTo, value);
1389+
}
13881390
}
1389-
}
1390-
Map<String, Object> objectAttributes = new HashMap<>();
1391-
for (Map.Entry<String, String> entry : finalAttributes.entrySet()) {
1392-
if(!entry.getKey().equals(Constants.MessageKey.SANDBOX_MODE_ROKT)) {
1393-
objectAttributes.put(entry.getKey(), entry.getValue());
1391+
Map<String, Object> objectAttributes = new HashMap<>();
1392+
for (Map.Entry<String, String> entry : finalAttributes.entrySet()) {
1393+
if (!entry.getKey().equals(Constants.MessageKey.SANDBOX_MODE_ROKT)) {
1394+
objectAttributes.put(entry.getKey(), entry.getValue());
1395+
}
1396+
}
1397+
if (user != null) {
1398+
user.setUserAttributes(objectAttributes);
13941399
}
1395-
}
1396-
if (user != null) {
1397-
user.setUserAttributes(objectAttributes);
1398-
}
13991400

1400-
if (!finalAttributes.containsKey(Constants.MessageKey.SANDBOX_MODE_ROKT)) {
1401-
finalAttributes.put(Constants.MessageKey.SANDBOX_MODE_ROKT, String.valueOf(Objects.toString(MPUtility.isDevEnv(), "false"))); // Default value is "false" if null
1402-
}
1401+
if (!finalAttributes.containsKey(Constants.MessageKey.SANDBOX_MODE_ROKT)) {
1402+
finalAttributes.put(Constants.MessageKey.SANDBOX_MODE_ROKT, Objects.toString(MPUtility.isDevEnv(), "false")); // Default value is "false" if null
1403+
}
14031404

1404-
((KitIntegration.RoktListener) provider).execute(viewName,
1405-
finalAttributes,
1406-
mpRoktEventCallback,
1407-
placeHolders,
1408-
fontTypefaces,
1409-
FilteredMParticleUser.getInstance(user.getId(), provider),
1410-
config);
1405+
((KitIntegration.RoktListener) provider).execute(viewName,
1406+
finalAttributes,
1407+
mpRoktEventCallback,
1408+
placeHolders,
1409+
fontTypefaces,
1410+
FilteredMParticleUser.getInstance(user.getId(), provider),
1411+
config);
14111412
});
14121413
}
14131414
} catch (Exception e) {
@@ -1416,6 +1417,15 @@ public void execute(@NonNull String viewName,
14161417
}
14171418
}
14181419

1420+
private String getValueIgnoreCase(Map<String, String> map, String searchKey) {
1421+
for (Map.Entry<String, String> entry : map.entrySet()) {
1422+
if (entry.getKey().equalsIgnoreCase(searchKey)) {
1423+
return entry.getValue();
1424+
}
1425+
}
1426+
return null;
1427+
}
1428+
14191429
@Override
14201430
public Flow<RoktEvent> events(@NonNull String identifier) {
14211431
for (KitIntegration provider : providers.values()) {
@@ -1473,43 +1483,63 @@ public void close() {
14731483

14741484
private void confirmEmail(
14751485
@Nullable String email,
1486+
@Nullable String hashedEmail,
14761487
@Nullable MParticleUser user,
14771488
IdentityApi identityApi,
14781489
Runnable runnable
14791490
) {
1480-
if (email != null && user != null) {
1491+
boolean hasEmail = email != null && !email.isEmpty();
1492+
boolean hasHashedEmail = hashedEmail != null && !hashedEmail.isEmpty();
1493+
1494+
if ((hasEmail || hasHashedEmail) && user != null) {
14811495
String existingEmail = user.getUserIdentities().get(MParticle.IdentityType.Email);
1496+
String existingHashedEmail = user.getUserIdentities().get(MParticle.IdentityType.Other);
1497+
1498+
boolean emailMismatch = hasEmail && !email.equalsIgnoreCase(existingEmail);
1499+
boolean hashedEmailMismatch = hasHashedEmail && !hashedEmail.equalsIgnoreCase(existingHashedEmail);
14821500

1483-
if (!email.equals(existingEmail)) {
1501+
if (emailMismatch || hashedEmailMismatch) {
14841502
// If there's an existing email but it doesn't match the passed-in email, log a warning
1485-
if (existingEmail != null) {
1486-
Logger.warning( String.format(
1503+
if (emailMismatch && existingEmail != null) {
1504+
Logger.warning(String.format(
14871505
"The existing email on the user (%s) does not match the email passed to selectPlacements (%s). " +
14881506
"Please make sure to sync the email identity to mParticle as soon as it's available. " +
14891507
"Identifying user with the provided email before continuing to selectPlacements.",
14901508
existingEmail, email
14911509
));
14921510
}
1511+
// If there's an existing other but it doesn't match the passed-in hashed email, log a warning
1512+
else if (hashedEmailMismatch && existingHashedEmail != null) {
1513+
Logger.warning(String.format(
1514+
"The existing hashed email on the user (%s) does not match the hashed email passed to selectPlacements (%s). " +
1515+
"Please make sure to sync the hashed email identity to mParticle as soon as it's available. " +
1516+
"Identifying user with the provided hashed email before continuing to selectPlacements.",
1517+
existingHashedEmail, hashedEmail
1518+
));
1519+
}
14931520

1494-
IdentityApiRequest identityRequest = IdentityApiRequest.withUser(user)
1495-
.email(email)
1496-
.build();
1521+
IdentityApiRequest.Builder identityBuilder = IdentityApiRequest.withUser(user);
1522+
if (emailMismatch) {
1523+
identityBuilder.email(email);
1524+
}
1525+
if (hashedEmailMismatch) {
1526+
identityBuilder.userIdentity(MParticle.IdentityType.Other, hashedEmail);
1527+
}
1528+
1529+
IdentityApiRequest identityRequest = identityBuilder.build();
14971530
MParticleTask<IdentityApiResult> task = identityApi.identify(identityRequest);
1498-
task.addFailureListener(new TaskFailureListener() {
1499-
@Override
1500-
public void onFailure(IdentityHttpResponse result) {
1501-
Logger.error( "Failed to sync email from selectPlacement to user: " + result.getErrors().toString());
15021531

1503-
runnable.run();
1504-
}
1532+
task.addFailureListener(result -> {
1533+
Logger.error("Failed to sync email from selectPlacement to user: " + result.getErrors());
1534+
runnable.run();
15051535
});
1506-
task.addSuccessListener(new TaskSuccessListener() {
1507-
@Override
1508-
public void onSuccess(IdentityApiResult result) {
1509-
Logger.debug("Updated email identity based on selectPlacement's attributes: " + result.getUser().getUserIdentities().get(MParticle.IdentityType.Email));
1510-
runnable.run();
1511-
}
1536+
1537+
task.addSuccessListener(result -> {
1538+
Logger.debug("Updated email identity based on selectPlacement's attributes: " +
1539+
result.getUser().getUserIdentities().get(MParticle.IdentityType.Email));
1540+
runnable.run();
15121541
});
1542+
15131543
} else {
15141544
runnable.run();
15151545
}

0 commit comments

Comments
 (0)