Skip to content

Commit

Permalink
Dev -> staging for 1.0.0 release (#43)
Browse files Browse the repository at this point in the history
* Use GPG_KEY_ID secret in script (#38)

* Use GPG_KEY_ID secret in script (#37)

* Set mock network service for functional tests (#41)

* Read ECID from IdentityDirect on Boot when registered (#40)

* [AMSDK-11399] Handle install scenario, when Identity direct registered

* [AMSDK-11399] Cleanup, IdentityState unit tests

* Rename test app

* [AMSDK-11399] Add docs for new code

* [AMSDK-11399] Cache events locally until the extension is booted up

* [AMSDK-11399] Fix unit tests

* Code format

* [AMSDK-11399] New tests, fix resetIdentities event source

* [AMSDK-11399] Cleanup

* [AMSDK-11399] Fix null check for getApi

* [AMSDK-11399] Review - docs, cleanup

* Update core version 1.8.0 (#42)

* Fetch identity shared state when needed (#44)
  • Loading branch information
emdobrin authored Apr 8, 2021
1 parent 295e1f3 commit 17c5ee4
Show file tree
Hide file tree
Showing 36 changed files with 1,124 additions and 543 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/maven-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ jobs:
run: |
echo $GPG_SECRET_KEYS | base64 --decode | gpg --import --no-tty --batch --yes
echo $GPG_OWNERTRUST | base64 --decode | gpg --import-ownertrust --no-tty --batch --yes
echo "GPG_KEY_ID=$(gpg -k --with-colons | grep 'pub' | cut -d':' -f5 | tail -c 9)" >> $GITHUB_ENV
- name: Publish to maven central staging repository
run: make ci-publish-main
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
3 changes: 2 additions & 1 deletion .github/workflows/maven-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ jobs:
run: |
echo $GPG_SECRET_KEYS | base64 --decode | gpg --import --no-tty --batch --yes
echo $GPG_OWNERTRUST | base64 --decode | gpg --import-ownertrust --no-tty --batch --yes
echo "GPG_KEY_ID=$(gpg -k --with-colons | grep 'pub' | cut -d':' -f5 | tail -c 9)" >> $GITHUB_ENV
- name: Publish to maven central staging repository
run: make ci-publish-staging
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}

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
6 changes: 0 additions & 6 deletions code/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ buildscript {
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }

// TODO: the following url can be removed once core is migrated to the new release process
maven { url "https://eaps.bintray.com/mobileservicesdk" }
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
Expand All @@ -26,9 +23,6 @@ allprojects {
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }

// TODO: the following url can be removed once core is migrated to the new release process
maven { url "https://eaps.bintray.com/mobileservicesdk" }
}

apply plugin: 'maven-publish'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
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;

import com.adobe.marketing.mobile.services.HttpConnecting;
import com.adobe.marketing.mobile.services.NetworkCallback;
import com.adobe.marketing.mobile.services.NetworkRequest;
import com.adobe.marketing.mobile.services.Networking;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

/**
* Mock network service used by MobileCore for functional test cases.
* This network service returns '200' HttpConnection responses for every request.
*/
class MockNetworkService implements Networking {
private static String TAG = "MockNetworkService";

private static HttpConnecting dummyConnection = new HttpConnecting() {
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream("{}".getBytes());
}

@Override
public InputStream getErrorStream() {
return null;
}

@Override
public int getResponseCode() {
return 200;
}

@Override
public String getResponseMessage() {
return null;
}

@Override
public String getResponsePropertyValue(String s) {
return null;
}

@Override
public void close() {

}
};

@Override
public void connectAsync(NetworkRequest networkRequest, NetworkCallback networkCallback) {
if (networkRequest == null) {
return;
}

MobileCore.log(LoggingMode.DEBUG, TAG, "Received async request '" + networkRequest.getUrl() + "', ignoring.");

if (networkCallback != null) {
networkCallback.call(dummyConnection);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import com.adobe.marketing.mobile.MonitorExtension.EventSpec;
import com.adobe.marketing.mobile.edge.identity.ADBCountDownLatch;
import com.adobe.marketing.mobile.services.ServiceProvider;

import androidx.test.platform.app.InstrumentationRegistry;

Expand Down Expand Up @@ -76,6 +77,7 @@ public void evaluate() throws Throwable {
defaultApplication = Instrumentation.newApplication(CustomApplication.class, context);
}

ServiceProvider.getInstance().setNetworkService(new MockNetworkService()); // set mock network service for testing
MobileCore.setLogLevel(LoggingMode.VERBOSE);
MobileCore.setApplication(defaultApplication);

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
Expand Up @@ -15,8 +15,19 @@
* Represents the authentication state for an {@link IdentityItem}
*/
public enum AuthenticatedState {
/**
* The state is ambiguous.
*/
AMBIGUOUS("ambiguous"),

/**
* User identified by a login or similar action that was valid at the time of the event observation.
*/
AUTHENTICATED("authenticated"),

/**
* User was identified by a login action at some point of time previously, but is not currently logged in.
*/
LOGGED_OUT("loggedOut");

private String name;
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}
*
* @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 state update for the provided {@code stateOwnerName}
*/
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) {
ECID legacyEcid = null;

try {
final String legacyEcidString = (String) identityDirectSharedState.get(
IdentityConstants.SharedState.IdentityDirect.ECID);
legacyEcid = legacyEcidString == null ? null : new ECID(legacyEcidString);
} catch (ClassCastException e) {
MobileCore.log(LoggingMode.DEBUG, LOG_TAG,
"EventUtils - Failed to extract ECID from Identity direct shared state, expected String: "
+ e.getLocalizedMessage());
}

return legacyEcid;
}
}
Loading

0 comments on commit 17c5ee4

Please sign in to comment.