From 3bd6da76dd0478d461ce91fe41678d6c9a58ebd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyady=20Mih=C3=A1ly?= Date: Wed, 20 Sep 2023 14:58:38 +0200 Subject: [PATCH 1/5] chore(gradle): update dependencies SUITEDEV-34202 Co-authored-by: davidSchuppa <32750715+davidSchuppa@users.noreply.github.com> Co-authored-by: LasOri <24588073+LasOri@users.noreply.github.com> --- .github/workflows/on_tag_workflow.yml | 2 +- sample/build.gradle | 30 +++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/on_tag_workflow.yml b/.github/workflows/on_tag_workflow.yml index dcee32c6..90be9465 100644 --- a/.github/workflows/on_tag_workflow.yml +++ b/.github/workflows/on_tag_workflow.yml @@ -74,7 +74,7 @@ jobs: run: echo $ANDROID_HOME > local.properties - name: Release with Gradle - run: ./gradlew clean assembleRelease publishToSonatype + run: ./gradlew clean assembleRelease && ./gradlew publishToSonatype - name: Create file 'FAILURE.TXT' and write 'true' into it if: ${{ failure() }} diff --git a/sample/build.gradle b/sample/build.gradle index ca33d7da..0f05de6f 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -81,13 +81,13 @@ buildscript { maven { url 'https://developer.huawei.com/repo/' } } dependencies { - classpath 'com.google.gms:google-services:4.3.15' + classpath 'com.google.gms:google-services:4.4.0' classpath 'com.huawei.agconnect:agcp:1.9.1.300' } } dependencies { - if (project.devConfig.useLocalDependency || System.env.DEVELOPMENT_MODE) { + if (project.devConfig.useLocalDependency == true || System.env.DEVELOPMENT_MODE == true) { implementation project(':emarsys-sdk') implementation project(':emarsys-firebase') implementation project(':emarsys-huawei') @@ -99,39 +99,39 @@ dependencies { // Getting a "Could not find firebase-core" error? Make sure you have // the latest Google Repository in the Android SDK manager - implementation "org.jetbrains.kotlin:kotlin-reflect:1.9.0" - implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0" + implementation "org.jetbrains.kotlin:kotlin-reflect:1.9.10" + implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.10" implementation 'com.google.android.material:material:1.9.0' implementation 'com.android.support:cardview-v7:28.0.0' - implementation 'com.google.android.gms:play-services-auth:20.6.0' + implementation 'com.google.android.gms:play-services-auth:20.7.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'io.coil-kt:coil:2.4.0' - implementation "androidx.core:core-ktx:1.10.1" + implementation "androidx.core:core-ktx:1.12.0" implementation "com.google.android.material:material:1.9.0" - implementation "androidx.compose.ui:ui:1.4.3" - implementation "androidx.compose.material:material:1.4.3" - implementation "androidx.compose.ui:ui-tooling-preview:1.4.3" - implementation "androidx.navigation:navigation-compose:2.6.0" - implementation "androidx.compose.material:material-icons-extended:1.4.3" - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1" + implementation "androidx.compose.ui:ui:1.5.1" + implementation "androidx.compose.material:material:1.5.1" + implementation "androidx.compose.ui:ui-tooling-preview:1.5.1" + implementation "androidx.navigation:navigation-compose:2.7.2" + implementation "androidx.compose.material:material-icons-extended:1.5.1" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2" implementation "androidx.activity:activity-compose:1.7.2" implementation "io.coil-kt:coil-compose:2.4.0" implementation "androidx.datastore:datastore-preferences:1.0.0" implementation "com.chibatching.kotpref:kotpref:2.13.2" implementation "com.google.firebase:firebase-common-ktx:20.3.3" implementation "com.google.firebase:firebase-messaging-ktx:23.2.1" - implementation "com.google.android.gms:play-services-auth:20.6.0" + implementation "com.google.android.gms:play-services-auth:20.7.0" implementation "com.google.accompanist:accompanist-swiperefresh:0.30.1" implementation "com.google.code.gson:gson:2.10.1" - debugImplementation "androidx.compose.ui:ui-tooling:1.4.3" + debugImplementation "androidx.compose.ui:ui-tooling:1.5.1" testImplementation 'junit:junit:4.13.2' androidTestImplementation "androidx.test.ext:junit:1.1.5" androidTestImplementation "androidx.test.espresso:espresso-core:3.5.1" - androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.4.3" + androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.5.1" androidTestImplementation 'androidx.test:rules:1.5.0' androidTestImplementation 'androidx.test:runner:1.5.2' androidTestImplementation('com.adevinta.android:barista:4.3.0') { From 67f8b5a38ae5fe1005a936edfed48c02f6896a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyady=20Mih=C3=A1ly?= Date: Wed, 20 Sep 2023 15:28:33 +0200 Subject: [PATCH 2/5] chore(gradle): update dependencies SUITEDEV-34202 Co-authored-by: davidSchuppa <32750715+davidSchuppa@users.noreply.github.com> Co-authored-by: LasOri <24588073+LasOri@users.noreply.github.com> --- build.gradle | 4 ++-- buildSrc/src/main/java/Config.kt | 2 +- sample/build.gradle | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a4b262d9..9021d21c 100644 --- a/build.gradle +++ b/build.gradle @@ -13,11 +13,11 @@ buildscript { gradlePluginPortal() } dependencies { - classpath 'com.android.tools.build:gradle:8.1.0' + classpath 'com.android.tools.build:gradle:8.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$Versions.kotlin_version" classpath "org.jetbrains.kotlin:kotlin-allopen:$Versions.kotlin_version" classpath "com.github.ben-manes:gradle-versions-plugin:0.47.0" - classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.6.0" + classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.2" classpath "io.github.gradle-nexus:publish-plugin:1.3.0" } } diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index 4defb99c..6f3bc7d0 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -1,5 +1,5 @@ object Config { const val minApiLevel = 24 - const val targetApiLevel = 33 + const val targetApiLevel = 34 const val buildToolsVersion = Versions.buildToolsVersion } diff --git a/sample/build.gradle b/sample/build.gradle index 0f05de6f..a68438f8 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -11,7 +11,7 @@ android { defaultConfig { applicationId "com.emarsys.sample" minSdkVersion 24 - targetSdkVersion 33 + targetSdkVersion 34 multiDexEnabled true versionCode gitVersionCode versionName gitVersionName From 433ac8127eb8919764e290efb25bd1365e7352db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyady=20Mih=C3=A1ly?= Date: Wed, 22 Nov 2023 14:14:39 +0100 Subject: [PATCH 3/5] chore(release): 3.6.2 SUITEDEV-34747 Co-authored-by: davidSchuppa <32750715+davidSchuppa@users.noreply.github.com> Co-authored-by: LordAndras <49073629+LordAndras@users.noreply.github.com> Co-authored-by: matusekma <36794575+matusekma@users.noreply.github.com> --- changelog.md | 10 ++-------- emarsys-sdk/src/main/AndroidManifest.xml | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index 3479076c..4b15f98e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,11 +1,5 @@ -# What's changed +# What's fixed ### [Emarsys SDK](https://github.com/emartech/android-emarsys-sdk) -* Proguard rule added for Emarsys SDK to prevent issues when host application uses R8# What's - changed - -### [Emarsys SDK](https://github.com/emartech/android-emarsys-sdk) - -* Prevent requests without an application code from being sent and return an - InvalidArgumentException instead through the CompletionListener +* Fixed a possible security vulnerability around push messages \ No newline at end of file diff --git a/emarsys-sdk/src/main/AndroidManifest.xml b/emarsys-sdk/src/main/AndroidManifest.xml index db6302a3..9c9b0919 100644 --- a/emarsys-sdk/src/main/AndroidManifest.xml +++ b/emarsys-sdk/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ + android:exported="false" + android:theme="@style/Theme.AppCompat.Translucent" /> From 3b225817b96dd1f05b82fdd6f99a0282a73ab664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyady=20Mih=C3=A1ly?= Date: Wed, 22 Nov 2023 16:40:18 +0100 Subject: [PATCH 4/5] test(denna): fix denna tests SUITEDEV-34747 Co-authored-by: davidSchuppa <32750715+davidSchuppa@users.noreply.github.com> Co-authored-by: LordAndras <49073629+LordAndras@users.noreply.github.com> Co-authored-by: matusekma <36794575+matusekma@users.noreply.github.com> --- .../core/request/RequestManagerDennaTest.kt | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/core/src/androidTest/java/com/emarsys/core/request/RequestManagerDennaTest.kt b/core/src/androidTest/java/com/emarsys/core/request/RequestManagerDennaTest.kt index 151f0035..2c2eecb4 100644 --- a/core/src/androidTest/java/com/emarsys/core/request/RequestManagerDennaTest.kt +++ b/core/src/androidTest/java/com/emarsys/core/request/RequestManagerDennaTest.kt @@ -25,7 +25,11 @@ import com.emarsys.testUtil.InstrumentationRegistry.Companion.getTargetContext import com.emarsys.testUtil.TestUrls.DENNA_ECHO import com.emarsys.testUtil.TimeoutUtils.timeoutRule import org.json.JSONObject -import org.junit.* +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test import org.junit.rules.TestRule import org.mockito.kotlin.any import org.mockito.kotlin.doAnswer @@ -132,10 +136,10 @@ class RequestManagerDennaTest { Assert.assertEquals(200, fakeCompletionHandler.successResponseModel.statusCode.toLong()) val responseJson = JSONObject(fakeCompletionHandler.successResponseModel.body!!) val headers = responseJson["headers"] as JSONObject - Assert.assertEquals("value1", headers["Header1"]) - Assert.assertEquals("value2", headers["Header2"]) - Assert.assertEquals("application/json", headers["Accept"]) - Assert.assertEquals("application/x-www-form-urlencoded", headers["Content"]) + Assert.assertEquals("value1", headers["Header1".lowercase()]) + Assert.assertEquals("value2", headers["Header2".lowercase()]) + Assert.assertEquals("application/json", headers["Accept".lowercase()]) + Assert.assertEquals("application/x-www-form-urlencoded", headers["Content".lowercase()]) Assert.assertEquals("GET", responseJson["method"]) Assert.assertFalse(responseJson.has("body")) } @@ -166,10 +170,10 @@ class RequestManagerDennaTest { val responseJson = JSONObject(fakeCompletionHandler.successResponseModel.body!!) val headers = responseJson.getJSONObject("headers") val body = responseJson.getJSONObject("body") - Assert.assertEquals("value1", headers["Header1"]) - Assert.assertEquals("value2", headers["Header2"]) - Assert.assertEquals("application/json", headers["Accept"]) - Assert.assertEquals("application/x-www-form-urlencoded", headers["Content"]) + Assert.assertEquals("value1", headers["Header1".lowercase()]) + Assert.assertEquals("value2", headers["Header2".lowercase()]) + Assert.assertEquals("application/json", headers["Accept".lowercase()]) + Assert.assertEquals("application/x-www-form-urlencoded", headers["Content".lowercase()]) Assert.assertEquals("POST", responseJson["method"]) Assert.assertEquals("val1", body["key1"]) Assert.assertEquals("val2", body["key2"]) @@ -194,10 +198,10 @@ class RequestManagerDennaTest { Assert.assertEquals(200, fakeCompletionHandler.successResponseModel.statusCode.toLong()) val responseJson = JSONObject(fakeCompletionHandler.successResponseModel!!.body!!) val headers = responseJson.getJSONObject("headers") - Assert.assertEquals("value1", headers["Header1"]) - Assert.assertEquals("value2", headers["Header2"]) - Assert.assertEquals("application/json", headers["Accept"]) - Assert.assertEquals("application/x-www-form-urlencoded", headers["Content"]) + Assert.assertEquals("value1", headers["Header1".lowercase()]) + Assert.assertEquals("value2", headers["Header2".lowercase()]) + Assert.assertEquals("application/json", headers["Accept".lowercase()]) + Assert.assertEquals("application/x-www-form-urlencoded", headers["Content".lowercase()]) Assert.assertEquals("PUT", responseJson["method"]) Assert.assertFalse(responseJson.has("body")) } @@ -216,10 +220,10 @@ class RequestManagerDennaTest { Assert.assertEquals(200, fakeCompletionHandler.successResponseModel.statusCode.toLong()) val responseJson = JSONObject(fakeCompletionHandler.successResponseModel!!.body!!) val headers = responseJson.getJSONObject("headers") - Assert.assertEquals("value1", headers["Header1"]) - Assert.assertEquals("value2", headers["Header2"]) - Assert.assertEquals("application/json", headers["Accept"]) - Assert.assertEquals("application/x-www-form-urlencoded", headers["Content"]) + Assert.assertEquals("value1", headers["Header1".lowercase()]) + Assert.assertEquals("value2", headers["Header2".lowercase()]) + Assert.assertEquals("application/json", headers["Accept".lowercase()]) + Assert.assertEquals("application/x-www-form-urlencoded", headers["Content".lowercase()]) Assert.assertEquals("DELETE", responseJson["method"]) Assert.assertFalse(responseJson.has("body")) } From 833f7c9e47fe88e035c0efa70d649107f53cce88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyady=20Mih=C3=A1ly?= Date: Thu, 23 Nov 2023 15:36:15 +0100 Subject: [PATCH 5/5] test(predict): fix integration tests SUITEDEV-34747 Co-authored-by: davidSchuppa <32750715+davidSchuppa@users.noreply.github.com> --- .../com/emarsys/PredictIntegrationTest.kt | 89 +++++++++++-------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/emarsys-sdk/src/androidTest/java/com/emarsys/PredictIntegrationTest.kt b/emarsys-sdk/src/androidTest/java/com/emarsys/PredictIntegrationTest.kt index 41eeac99..4a235eab 100644 --- a/emarsys-sdk/src/androidTest/java/com/emarsys/PredictIntegrationTest.kt +++ b/emarsys-sdk/src/androidTest/java/com/emarsys/PredictIntegrationTest.kt @@ -1,5 +1,6 @@ package com.emarsys + import android.app.Application import android.content.Context import com.emarsys.config.EmarsysConfig @@ -7,9 +8,6 @@ import com.emarsys.core.DefaultCoreCompletionHandler import com.emarsys.core.api.result.Try import com.emarsys.core.device.DeviceInfo import com.emarsys.core.device.LanguageProvider - - - import com.emarsys.core.notification.NotificationManagerHelper import com.emarsys.core.provider.hardwareid.HardwareIdProvider import com.emarsys.core.provider.version.VersionProvider @@ -18,20 +16,28 @@ import com.emarsys.core.storage.Storage import com.emarsys.di.DefaultEmarsysComponent import com.emarsys.di.DefaultEmarsysDependencies import com.emarsys.di.emarsys - import com.emarsys.predict.api.model.PredictCartItem import com.emarsys.predict.api.model.Product import com.emarsys.predict.api.model.RecommendationFilter import com.emarsys.predict.api.model.RecommendationLogic import com.emarsys.predict.util.CartItemUtils -import com.emarsys.testUtil.* +import com.emarsys.testUtil.ConnectionTestUtils +import com.emarsys.testUtil.DatabaseTestUtils +import com.emarsys.testUtil.FeatureTestUtils +import com.emarsys.testUtil.InstrumentationRegistry +import com.emarsys.testUtil.IntegrationTestUtils +import com.emarsys.testUtil.RetryUtils +import com.emarsys.testUtil.TimeoutUtils import com.emarsys.testUtil.mockito.whenever import com.emarsys.testUtil.rules.DuplicatedThreadRule import com.emarsys.testUtil.rules.RetryRule import io.kotlintest.matchers.numerics.shouldBeGreaterThan import io.kotlintest.shouldBe import io.kotlintest.shouldNotBe -import org.junit.* +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test import org.junit.rules.TestRule import org.mockito.ArgumentMatchers import org.mockito.Mockito.mock @@ -45,6 +51,11 @@ class PredictIntegrationTest { private const val CONTACT_FIELD_ID = 3 private const val MERCHANT_ID = "1428C8EE286EC34B" private const val OTHER_MERCHANT_ID = "test_1428C8EE286EC34B" + const val ITEM1 = "12800" + const val ITEM2 = "13433" + const val ITEM3 = "9129-P" + const val SEARCH_TERM = "Ropa" + const val CATEGORY_PATH = "Ropa bebe nina>Ropa Interior" } private lateinit var latch: CountDownLatch @@ -165,9 +176,9 @@ class PredictIntegrationTest { @Test fun testTrackCart() { val cartItems = listOf( - PredictCartItem("2168", 1.1, 10.0), - PredictCartItem("2200", 2.2, 20.0), - PredictCartItem("2509", 3.3, 30.0) + PredictCartItem(ITEM1, 1.1, 10.0), + PredictCartItem(ITEM2, 2.2, 20.0), + PredictCartItem(ITEM3, 3.3, 30.0) ) responseModelMatches = { @@ -182,9 +193,9 @@ class PredictIntegrationTest { @Test fun testTrackPurchase() { val cartItems = listOf( - PredictCartItem("2168", 1.1, 10.0), - PredictCartItem("2200", 2.2, 20.0), - PredictCartItem("2509", 3.3, 30.0) + PredictCartItem(ITEM1, 1.1, 10.0), + PredictCartItem(ITEM2, 2.2, 20.0), + PredictCartItem(ITEM3, 3.3, 30.0) ) val orderId = "orderId_1234567892345678" @@ -201,7 +212,7 @@ class PredictIntegrationTest { @Test fun testTrackItemView() { - val itemId = "2168" + val itemId = ITEM3 responseModelMatches = { it.baseUrl.contains(itemId) } @@ -213,7 +224,7 @@ class PredictIntegrationTest { @Test fun testTrackItemView_withProduct() { - val product = Product("2168", "TestTitle", "https://emarsys.com", "RELATED", "AAAA") + val product = Product(ITEM3, "TestTitle", "https://emarsys.com", "RELATED", "AAAA") responseModelMatches = { it.baseUrl.contains(product.productId) } @@ -225,24 +236,22 @@ class PredictIntegrationTest { @Test fun testTrackCategoryView() { - val categoryId = "MEN>Shirts" responseModelMatches = { - it.baseUrl.contains(categoryId) + it.baseUrl.contains(CATEGORY_PATH) } - Emarsys.predict.trackCategoryView(categoryId) + Emarsys.predict.trackCategoryView(CATEGORY_PATH) eventuallyAssertSuccess() } @Test fun testTrackSearchTerm() { - val searchTerm = "polo shirt" responseModelMatches = { - it.baseUrl.contains(searchTerm) + it.baseUrl.contains(SEARCH_TERM) } - Emarsys.predict.trackSearchTerm(searchTerm) + Emarsys.predict.trackSearchTerm(SEARCH_TERM) eventuallyAssertSuccess() } @@ -261,10 +270,12 @@ class PredictIntegrationTest { @Test fun testRecommendProducts() { - Emarsys.predict.recommendProducts(RecommendationLogic.search("polo shirt"), - listOf(RecommendationFilter.exclude("price").isValue("")), - 3, - eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter)).eventuallyAssert { + Emarsys.predict.recommendProducts( + RecommendationLogic.search(SEARCH_TERM), + listOf(RecommendationFilter.exclude("price").isValue("")), + 3, + eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter) + ).eventuallyAssert { latch.await() triedRecommendedProducts.errorCause shouldBe null @@ -274,8 +285,10 @@ class PredictIntegrationTest { @Test fun testRecommendProducts_withSearch() { - Emarsys.predict.recommendProducts(RecommendationLogic.search("polo shirt"), - eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter)) + Emarsys.predict.recommendProducts( + RecommendationLogic.search(SEARCH_TERM), + eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter) + ) eventuallyAssertForTriedRecommendedProducts() } @@ -294,9 +307,9 @@ class PredictIntegrationTest { @Test fun testRecommendProducts_withCart() { val cartItems = listOf( - PredictCartItem("2168", 1.1, 10.0), - PredictCartItem("2200", 2.2, 20.0), - PredictCartItem("2509", 3.3, 30.0) + PredictCartItem(ITEM1, 1.1, 10.0), + PredictCartItem(ITEM2, 2.2, 20.0), + PredictCartItem(ITEM3, 3.3, 30.0) ) Emarsys.predict.recommendProducts(RecommendationLogic.cart(cartItems), eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter)) @@ -317,8 +330,10 @@ class PredictIntegrationTest { @Test fun testRecommendProducts_withRelated() { - Emarsys.predict.recommendProducts(RecommendationLogic.related("2200"), - eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter)) + Emarsys.predict.recommendProducts( + RecommendationLogic.related(ITEM3), + eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter) + ) eventuallyAssertForTriedRecommendedProducts() } @@ -346,8 +361,10 @@ class PredictIntegrationTest { @Test fun testRecommendProducts_withCategory() { - Emarsys.predict.recommendProducts(RecommendationLogic.category("MEN>Shirts"), - eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter)) + Emarsys.predict.recommendProducts( + RecommendationLogic.category(CATEGORY_PATH), + eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter) + ) eventuallyAssertForTriedRecommendedProducts() } @@ -365,8 +382,10 @@ class PredictIntegrationTest { @Test fun testRecommendProducts_withAlsoBought() { - Emarsys.predict.recommendProducts(RecommendationLogic.alsoBought("2200"), - eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter)) + Emarsys.predict.recommendProducts( + RecommendationLogic.alsoBought(ITEM1), + eventuallyStoreResultInProperty(this::triedRecommendedProducts.setter) + ) eventuallyAssertForTriedRecommendedProducts() }