Skip to content
Open
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
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ buildscript {
}

plugins {
id "org.sonarqube" version "3.5.0.2730"
id "org.sonarqube" version "4.4.1.3373"
id "org.jlleitschuh.gradle.ktlint" version "11.2.0"
}

Expand All @@ -36,5 +36,5 @@ apply plugin: 'com.mparticle.kit'

dependencies {
testImplementation fileTree(dir: 'libs', include: ['*.jar'])
compileOnly 'com.onetrust.cmp:native-sdk:202301.2.0.0'
compileOnly 'com.onetrust.cmp:native-sdk:202308.2.0.0'
}
115 changes: 9 additions & 106 deletions src/main/kotlin/com/mparticle/kits/OneTrustKit.kt
Original file line number Diff line number Diff line change
Expand Up @@ -103,119 +103,19 @@ class OneTrustKit : KitIntegration(), IdentityListener {
// 0 = Consent Not Given
// -1 = Consent has not been collected/ sdk is not yet initialized
internal fun processOneTrustConsents() {
val time = System.currentTimeMillis()
MParticle.getInstance()?.Identity()?.currentUser?.let { user ->
purposeConsentMapping.forEach { entry ->
val purpose = entry.key
val regulation = entry.value.regulation
val status = oneTrustSdk.getConsentStatusForGroupId(purpose)
purposeConsentMapping?.iterator()?.forEach { entry ->
val status = oneTrustSdk.getConsentStatusForGroupId(entry.key)

if (status != -1) {
createOrUpdateConsent(
user,
purpose,
status,
regulation,
time
)?.let { user.setConsentState(it) }
setConsentStateEvent(entry.value, status)
}
}
} ?: run {
Logger.warning("MParticle user is not set")
}
}

internal fun createOrUpdateConsent(
user: MParticleUser,
purpose: String?,
status: Int,
regulation: ConsentRegulation,
timestamp: Long
): ConsentState? {
var consentState: ConsentState? = null
when (regulation) {
ConsentRegulation.GDPR -> {
if (purpose == null) {
Logger.warning("Purpose is required for GDPR Consent Events")
return null
}
consentState = GDPRConsent
.builder(status == 1)
.timestamp(timestamp)
.build()
.updateTemporaryConsentState(user, purpose, timestamp)
}
ConsentRegulation.CCPA -> {
consentState = CCPAConsent
.builder(status == 1)
.timestamp(timestamp)
.build()
.updateTemporaryConsentState(user, timestamp)
}
}
return consentState
}

private fun CCPAConsent.updateTimestamp(timestamp: Long): CCPAConsent =
CCPAConsent.builder(this.isConsented).timestamp(timestamp)
.document(this.document).hardwareId(this.hardwareId).location(this.location).build()

private fun MutableMap<String, GDPRConsent>.updateTimestamps(timestamp: Long): MutableMap<String, GDPRConsent> {
this.entries.forEach {
val consent = it.value
this.put(
it.key, GDPRConsent.builder(consent.isConsented)
.timestamp(timestamp)
.document(consent.document)
.hardwareId(consent.hardwareId)
.location(consent.location)
.build()
)
}
return this
}

private fun CCPAConsent.updateTemporaryConsentState(
user: MParticleUser,
timestamp: Long
): ConsentState {
val builder = ConsentState.builder()
try {
builder.setCCPAConsentState(this)
builder.setGDPRConsentState(
user.consentState.gdprConsentState.toMutableMap().updateTimestamps(timestamp)
)
} catch (e: Exception) {
}
return builder.build()
}

private fun GDPRConsent.updateTemporaryConsentState(
user: MParticleUser,
purpose: String?,
timestamp: Long
): ConsentState {
val builder = ConsentState.builder()
try {
val currentConsent = user.consentState
currentConsent.ccpaConsentState?.let {
builder.setCCPAConsentState(
it.updateTimestamp(
timestamp
)
)
}
if (!purpose.isNullOrEmpty()) {
val mergedGDPRConsent: MutableMap<String, GDPRConsent> =
currentConsent.gdprConsentState.toMutableMap()
mergedGDPRConsent[purpose] = this
builder.setGDPRConsentState(mergedGDPRConsent)
}
} catch (e: Exception) {

}
return builder.build()
}

fun saveToDisk(key: String, mappingData: String?) {
val context = context
val sharedPreferences =
Expand Down Expand Up @@ -250,17 +150,20 @@ class OneTrustKit : KitIntegration(), IdentityListener {
val user = MParticle.getInstance()?.Identity()?.currentUser
?: Logger.warning("current user is not present").let { return }
val consented = status == 1
val time = System.currentTimeMillis()

val consentState = user.consentState.let { ConsentState.withConsentState(it) }
when (consentMapping.regulation) {
ConsentRegulation.GDPR -> {
consentState.addGDPRConsentState(
consentMapping.purpose,
GDPRConsent.builder(consented).build()
GDPRConsent.builder(consented)
.timestamp(time)
.build()
)
}
ConsentRegulation.CCPA -> {
consentState.setCCPAConsentState(CCPAConsent.builder(consented).build())
consentState.setCCPAConsentState(CCPAConsent.builder(consented).timestamp(time).build())
}
}
user.setConsentState(consentState.build())
Expand Down
190 changes: 96 additions & 94 deletions src/test/kotlin/com/mparticle/kits/OneTrustKitTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mparticle.kits

import android.content.Context
import com.mparticle.MParticleOptions
import com.mparticle.consent.CCPAConsent
import com.mparticle.consent.ConsentState
import com.mparticle.consent.GDPRConsent
Expand Down Expand Up @@ -44,105 +45,106 @@ class KitTests {
Assert.assertNotNull(e)
}

/**
* This test should ensure that whatever the consent state is, if a new GDPR consent is created,
* it should be added to the consent state GDPR map
*/
@Test
fun testCreateConsentEventGDPR() {
val timestamp = System.currentTimeMillis()
val user = Mockito.mock(MParticleUser::class.java)
val gdprConsent = GDPRConsent.builder(false).build()
var currentConsentState =
ConsentState.builder().addGDPRConsentState("purpose1", gdprConsent).build()
`when`(user.consentState).thenReturn(currentConsentState)
assertEquals(1, currentConsentState.gdprConsentState.size)
assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
assertNull(currentConsentState.ccpaConsentState)
currentConsentState =
kit.createOrUpdateConsent(
user,
"purpose2",
1,
OneTrustKit.ConsentRegulation.GDPR,
timestamp
)!!
assertEquals(2, currentConsentState.gdprConsentState.size)
assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
assertEquals(currentConsentState.gdprConsentState.get("purpose2")?.timestamp, timestamp)
assertTrue(currentConsentState.gdprConsentState.containsKey("purpose2"))
assertEquals(true, currentConsentState.gdprConsentState.get("purpose2")!!.isConsented)
assertNull(currentConsentState.ccpaConsentState)
}

/**
* This test must ensure that any CCPA consent creates is added to the constent state.
* By design a new CCPA consent overrides the previous one.
*/
@Test
fun testCreateConsentEventCCPA() {
val timestamp = System.currentTimeMillis()
val user = Mockito.mock(MParticleUser::class.java)
val ccpaConsent = CCPAConsent.builder(false).location("loc1").build()
var currentConsentState = ConsentState.builder().setCCPAConsentState(ccpaConsent).build()
`when`(user.consentState).thenReturn(currentConsentState)
assertEquals(0, currentConsentState.gdprConsentState.size)
assertEquals(ccpaConsent, currentConsentState.ccpaConsentState)
assertEquals("loc1", currentConsentState.ccpaConsentState?.location)
assertEquals(false, currentConsentState.ccpaConsentState?.isConsented)

currentConsentState =
kit.createOrUpdateConsent(
user,
"ccpa",
1,
OneTrustKit.ConsentRegulation.CCPA,
timestamp
)!!
assertEquals(0, currentConsentState.gdprConsentState.size)
assertEquals(currentConsentState.ccpaConsentState?.timestamp, timestamp)
assertEquals(true, currentConsentState.ccpaConsentState?.isConsented)
assertNull(currentConsentState.ccpaConsentState?.location)
}

@Test
fun testCreateUpdate() {
val timestamp = System.currentTimeMillis()
val user = Mockito.mock(MParticleUser::class.java)
val ccpaConsent = CCPAConsent.builder(false).timestamp(timestamp).build()
var currentConsentStateBuilder = ConsentState.builder().setCCPAConsentState(ccpaConsent)

val gdprConsent = GDPRConsent.builder(false).timestamp(timestamp).build()
var currentConsentState = currentConsentStateBuilder.addGDPRConsentState("purpose1", gdprConsent).build()
`when`(user.consentState).thenReturn(currentConsentState)
assertEquals(1, currentConsentState.gdprConsentState.size)
assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
currentConsentState =
kit.createOrUpdateConsent(
user,
"purpose2",
1,
OneTrustKit.ConsentRegulation.GDPR,
timestamp
)!!
assertEquals(2, currentConsentState.gdprConsentState.size)
assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
assertEquals(gdprConsent.timestamp, currentConsentState.gdprConsentState.get("purpose1")?.timestamp)
assertEquals(currentConsentState.gdprConsentState.get("purpose2")?.timestamp, timestamp)
assertTrue(currentConsentState.gdprConsentState.containsKey("purpose2"))
assertEquals(true, currentConsentState.gdprConsentState.get("purpose2")!!.isConsented)
assertEquals(currentConsentState.ccpaConsentState?.timestamp, timestamp)
assertEquals(false, currentConsentState.ccpaConsentState?.isConsented)
}
// /**
// * This test should ensure that whatever the consent state is, if a new GDPR consent is created,
// * it should be added to the consent state GDPR map
// */
// @Test
// fun testCreateConsentEventGDPR() {
// val timestamp = System.currentTimeMillis()
// val user = Mockito.mock(MParticleUser::class.java)
// val gdprConsent = GDPRConsent.builder(false).build()
// var currentConsentState =
// ConsentState.builder().addGDPRConsentState("purpose1", gdprConsent).build()
// `when`(user.consentState).thenReturn(currentConsentState)
// assertEquals(1, currentConsentState.gdprConsentState.size)
// assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
// assertNull(currentConsentState.ccpaConsentState)
// currentConsentState =
// kit.createOrUpdateConsent(
// user,
// "purpose2",
// 1,
// OneTrustKit.ConsentRegulation.GDPR,
// timestamp
// )!!
// assertEquals(2, currentConsentState.gdprConsentState.size)
// assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
// assertEquals(currentConsentState.gdprConsentState.get("purpose2")?.timestamp, timestamp)
// assertTrue(currentConsentState.gdprConsentState.containsKey("purpose2"))
// assertEquals(true, currentConsentState.gdprConsentState.get("purpose2")!!.isConsented)
// assertNull(currentConsentState.ccpaConsentState)
// }
//
// /**
// * This test must ensure that any CCPA consent creates is added to the constent state.
// * By design a new CCPA consent overrides the previous one.
// */
// @Test
// fun testCreateConsentEventCCPA() {
// val timestamp = System.currentTimeMillis()
// val user = Mockito.mock(MParticleUser::class.java)
// val ccpaConsent = CCPAConsent.builder(false).location("loc1").build()
// var currentConsentState = ConsentState.builder().setCCPAConsentState(ccpaConsent).build()
// `when`(user.consentState).thenReturn(currentConsentState)
// assertEquals(0, currentConsentState.gdprConsentState.size)
// assertEquals(ccpaConsent, currentConsentState.ccpaConsentState)
// assertEquals("loc1", currentConsentState.ccpaConsentState?.location)
// assertEquals(false, currentConsentState.ccpaConsentState?.isConsented)
//
// currentConsentState =
// kit.createOrUpdateConsent(
// user,
// "ccpa",
// 1,
// OneTrustKit.ConsentRegulation.CCPA,
// timestamp
// )!!
// assertEquals(0, currentConsentState.gdprConsentState.size)
// assertEquals(currentConsentState.ccpaConsentState?.timestamp, timestamp)
// assertEquals(true, currentConsentState.ccpaConsentState?.isConsented)
// assertNull(currentConsentState.ccpaConsentState?.location)
// }
//
// @Test
// fun testCreateUpdate() {
// val timestamp = System.currentTimeMillis()
// val user = Mockito.mock(MParticleUser::class.java)
// val ccpaConsent = CCPAConsent.builder(false).timestamp(timestamp).build()
// var currentConsentStateBuilder = ConsentState.builder().setCCPAConsentState(ccpaConsent)
//
// val gdprConsent = GDPRConsent.builder(false).timestamp(timestamp).build()
// var currentConsentState = currentConsentStateBuilder.addGDPRConsentState("purpose1", gdprConsent).build()
// `when`(user.consentState).thenReturn(currentConsentState)
// assertEquals(1, currentConsentState.gdprConsentState.size)
// assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
// currentConsentState =
// kit.createOrUpdateConsent(
// user,
// "purpose2",
// 1,
// OneTrustKit.ConsentRegulation.GDPR,
// timestamp
// )!!
// assertEquals(2, currentConsentState.gdprConsentState.size)
// assertEquals(gdprConsent, currentConsentState.gdprConsentState.get("purpose1"))
// assertEquals(gdprConsent.timestamp, currentConsentState.gdprConsentState.get("purpose1")?.timestamp)
// assertEquals(currentConsentState.gdprConsentState.get("purpose2")?.timestamp, timestamp)
// assertTrue(currentConsentState.gdprConsentState.containsKey("purpose2"))
// assertEquals(true, currentConsentState.gdprConsentState.get("purpose2")!!.isConsented)
// assertEquals(currentConsentState.ccpaConsentState?.timestamp, timestamp)
// assertEquals(false, currentConsentState.ccpaConsentState?.isConsented)
// }

@Test
@Throws(Exception::class)
fun testClassName() {
val factory = KitIntegrationFactory()
val integrations = factory.knownIntegrations
val options = Mockito.mock(MParticleOptions::class.java)
val factory = KitIntegrationFactory(options)
val integrations = factory.supportedKits.values
val className = kit.javaClass.name
for ((_, value) in integrations) {
if (value == className) {
for (integration in integrations) {
if (integration.name == className) {
return
}
}
Expand Down