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

Read ECID from IdentityDirect on Boot when registered #40

Merged
merged 12 commits into from
Apr 8, 2021
2 changes: 1 addition & 1 deletion code/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

<resources>
<string name="app_name">App</string>
<string name="app_name">Edge Identity App</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Edge Identity Test App</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,34 @@ public void testECID_loadsIdentityDirectECID() throws Exception {
}

@Test
public void testECID_whenBothExtensionRegistered() throws Exception {
public void testECID_whenBothExtensionRegistered_install() throws Exception {
// setup
registerBothIdentityExtensions();
registerBothIdentityExtensions(); // no ECID exists before this step

String directECID = getIdentityDirectECIDSync();
String edgeECID = getExperienceCloudIdSync();

// verify ECID
verifyPrimaryECID(directECID);
verifySecondaryECID(null);
assertEquals(directECID, edgeECID);
}

@Test
public void testECID_whenBothExtensionRegistered_migrationPath() throws Exception {
// setup
String existingECID = "legacyECID";
setIdentityDirectPersistedECID(existingECID);
registerBothIdentityExtensions();

String directECID = getIdentityDirectECIDSync();
String edgeECID = getExperienceCloudIdSync();

// verify ECID
verifyPrimaryECID(edgeECID);
verifySecondaryECID(directECID);
verifyPrimaryECID(directECID);
verifySecondaryECID(null);
assertEquals(directECID, edgeECID);
assertEquals(existingECID, edgeECID);
}

@Test
Expand Down Expand Up @@ -165,23 +183,20 @@ public void testECID_AreDifferentAfterResetIdentitiesAndPrivacyChange() throws E
@Test
public void testECID_DirectEcidIsRemovedOnPrivacyOptOut() throws Exception {
// setup
setIdentityDirectPersistedECID("legacyECID");
setEdgeIdentityPersistence(CreateIdentityMap("ECID", "edgeECID").asXDMMap());
registerBothIdentityExtensions();

String edgeECID = getExperienceCloudIdSync();
String directECID = getIdentityDirectECIDSync();

// verify ECID
verifyPrimaryECID(edgeECID);
verifySecondaryECID(directECID);

verifyPrimaryECID("edgeECID");
verifySecondaryECID("legacyECID");

// Set privacy opted-out
MobileCore.setPrivacyStatus(MobilePrivacyStatus.OPT_OUT);
TestHelper.waitForThreads(2000);
edgeECID = getExperienceCloudIdSync();

// verify that the secondary ECID is removed
verifyPrimaryECID(edgeECID);
verifyPrimaryECID("edgeECID");
verifySecondaryECID(null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.adobe.marketing.mobile.TestHelper.getXDMSharedStateFor;
import static com.adobe.marketing.mobile.TestHelper.resetTestExpectations;
Expand All @@ -45,7 +46,7 @@ public void call(Object o) {
}
});

latch.await();
latch.await(1000, TimeUnit.MILLISECONDS);
TestHelper.waitForThreads(2000);
resetTestExpectations();
}
Expand All @@ -58,7 +59,7 @@ static void registerIdentityDirectExtension() throws Exception {
{
put("global.privacy", "optedin");
put("experienceCloud.org", "testOrg@AdobeOrg");
put("experienceCloud.server", "notasever");
put("experienceCloud.server", "notaserver");
}
};
MobileCore.updateConfiguration(config);
Expand All @@ -72,7 +73,7 @@ public void call(Object o) {
}
});

latch.await();
latch.await(1000, TimeUnit.MILLISECONDS);
TestHelper.waitForThreads(2000);
resetTestExpectations();
}
Expand All @@ -85,12 +86,11 @@ static void registerBothIdentityExtensions() throws Exception {
{
put("global.privacy", "optedin");
put("experienceCloud.org", "testOrg@AdobeOrg");
put("experienceCloud.server", "notasever");
put("experienceCloud.server", "notaserver");
}
};
MobileCore.updateConfiguration(config);


com.adobe.marketing.mobile.edge.identity.Identity.registerExtension();
com.adobe.marketing.mobile.Identity.registerExtension();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
Copyright 2021 Adobe. All rights reserved.
This file is licensed to you 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 REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

package com.adobe.marketing.mobile.edge.identity;

import com.adobe.marketing.mobile.Event;
import com.adobe.marketing.mobile.LoggingMode;
import com.adobe.marketing.mobile.MobileCore;

import java.util.Map;

import static com.adobe.marketing.mobile.edge.identity.IdentityConstants.LOG_TAG;

/**
* Class for Event / Event data specific helpers.
*/
final class EventUtils {

/**
* Checks if the provided {@code event} is of type {@link IdentityConstants.EventType:EDGE_IDENTITY} and source {@link IdentityConstants.EventSource:REMOVE_IDENTITY}
emdobrin marked this conversation as resolved.
Show resolved Hide resolved
*
* @param event the event to verify
* @return true if both type and source match
*/
static boolean isRemoveIdentityEvent(final Event event) {
return event != null && IdentityConstants.EventType.EDGE_IDENTITY.equalsIgnoreCase(event.getType())
&& IdentityConstants.EventSource.REMOVE_IDENTITY.equalsIgnoreCase(event.getSource());
}

/**
* Checks if the provided {@code event} is of type {@link IdentityConstants.EventType:EDGE_IDENTITY} and source {@link IdentityConstants.EventSource:UPDATE_IDENTITY}
*
* @param event the event to verify
* @return true if both type and source match
*/
static boolean isUpdateIdentityEvent(final Event event) {
return event != null && IdentityConstants.EventType.EDGE_IDENTITY.equalsIgnoreCase(event.getType())
&& IdentityConstants.EventSource.UPDATE_IDENTITY.equalsIgnoreCase(event.getSource());
}

/**
* Checks if the provided {@code event} is of type {@link IdentityConstants.EventType:EDGE_IDENTITY} and source {@link IdentityConstants.EventSource:REQUEST_IDENTITY}
*
* @param event the event to verify
* @return true if both type and source match
*/
static boolean isRequestIdentityEvent(final Event event) {
return event != null && IdentityConstants.EventType.EDGE_IDENTITY.equalsIgnoreCase(event.getType())
&& IdentityConstants.EventSource.REQUEST_IDENTITY.equalsIgnoreCase(event.getSource());
}

/**
* Checks if the provided {@code event} is of type {@link IdentityConstants.EventType:GENERIC_IDENTITY} and source {@link IdentityConstants.EventSource:REQUEST_RESET}
*
* @param event the event to verify
* @return true if both type and source match
*/
static boolean isRequestResetEvent(final Event event) {
return event != null && IdentityConstants.EventType.GENERIC_IDENTITY.equalsIgnoreCase(event.getType())
&& IdentityConstants.EventSource.REQUEST_RESET.equalsIgnoreCase(event.getSource());
}

/**
* Checks if the provided {@code event} is a shared state update event for {@code stateOwnerName}
*
* @param stateOwnerName the shared state owner name; should not be null
* @param event current event to check; should not be null
* @return {@code boolean} indicating if it is the shared stage update for the provided {@code stateOwnerName}
emdobrin marked this conversation as resolved.
Show resolved Hide resolved
*/
static boolean isSharedStateUpdateFor(final String stateOwnerName, final Event event) {
if (Utils.isNullOrEmpty(stateOwnerName) || event == null) {
return false;
}

String stateOwner;

try {
stateOwner = (String) event.getEventData().get(IdentityConstants.SharedState.STATE_OWNER);
} catch (ClassCastException e) {
return false;
}

return stateOwnerName.equals(stateOwner);
}

/**
* Extracts the ECID from the Identity Direct shared state and returns it as an {@link ECID} object
*
* @param identityDirectSharedState the Identity Direct shared state data
* @return the ECID or null if not found or unable to parse the payload
*/
static ECID getECID(final Map<String, Object> identityDirectSharedState) {
emdobrin marked this conversation as resolved.
Show resolved Hide resolved
ECID legacyEcid = null;

try {
final String legacyEcidString = (String) identityDirectSharedState.get(
IdentityConstants.SharedState.IdentityDirect.ECID);
legacyEcid = legacyEcidString == null ? null : new ECID(legacyEcidString);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest not generating a new ECID here, just return null so the caller knows the ECID didn't exist in the shared state. In the code where this API is called, you check if legacyEcid == null and if not you set the Edge Identity ECID to this returned ECID and log something to the effect ECID migrated from direct Identity. However, if the shared state contains no ECID and you generate on here, then the log message is inaccurate as the ECID wasn't migrated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would return null if the legacyEcidString is null or unable to cast

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I see that now. Sorry, I misread the code. This looks good. 👍

} catch (ClassCastException e) {
MobileCore.log(LoggingMode.DEBUG, LOG_TAG,
"IdentityExtension - Could not process direct Identity shared state change event, failed to parse stored ECID as String: "
emdobrin marked this conversation as resolved.
Show resolved Hide resolved
+ e.getLocalizedMessage());
}

return legacyEcid;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,22 @@ final class EventNames {
private EventNames() { }
}

final class EventDataKeys {
static final String VISITOR_ID_ECID = "mid";
final class SharedState {
static final String STATE_OWNER = "stateowner";
private EventDataKeys() { }
}

final class SharedStateKeys {
static final String IDENTITY_DIRECT = "com.adobe.module.identity";
private SharedStateKeys() { }
final class Hub {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some cleanup on these constants

static final String NAME = "com.adobe.module.eventhub";
static final String EXTENSIONS = "extensions";
private Hub() {}
}

final class IdentityDirect {
static final String NAME = "com.adobe.module.identity";
static final String ECID = "mid";
private IdentityDirect() {}
}

private SharedState() { }
}

final class Namespaces {
Expand Down
Loading