From bdbd3fcde26813fd1d8ba70e6e7c6ddf0ffe7b59 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 11 Dec 2024 17:21:43 +0100 Subject: [PATCH 1/2] =?UTF-8?q?ajout=20d=C3=A9pendances=20crashlytics=20g4?= =?UTF-8?q?A,=20clarity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 10 ++++++++-- build.gradle.kts | 11 ++++++++--- consentium/build.gradle.kts | 2 +- gradle/libs.versions.toml | 30 +++++++++++++++++++++--------- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index dcf5ef3..3f7c1b0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -8,7 +8,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) alias(libs.plugins.hilt) - alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.serialization) } @@ -60,7 +60,10 @@ android { isShrinkResources = true signingConfig = signingConfigs.getByName(BuildType.RELEASE.name) - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) } } compileOptions { @@ -92,6 +95,9 @@ dependencies { ksp(libs.hilt.compiler) implementation(libs.hilt.navigation.compose) implementation(libs.matomo) + implementation(libs.clarity) + implementation(libs.ga4) + // Compose implementation(platform(libs.compose.bom)) diff --git a/build.gradle.kts b/build.gradle.kts index 168859e..a47fc9a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,12 +15,17 @@ plugins { // Agp alias(libs.plugins.android.library) apply false - //Hilt + // Hilt alias(libs.plugins.hilt) apply false + // Kotlin serialization + alias(libs.plugins.serialization) apply false - //Kotlin serialization - alias(libs.plugins.kotlin.serialization) apply false + // Firebase crashlytics + alias(libs.plugins.firebaseCrashlytics) apply false + + // Google services + alias(libs.plugins.googleServices) apply false } \ No newline at end of file diff --git a/consentium/build.gradle.kts b/consentium/build.gradle.kts index e020f67..2290378 100644 --- a/consentium/build.gradle.kts +++ b/consentium/build.gradle.kts @@ -45,7 +45,7 @@ dependencies { ksp(libs.hilt.compiler) // Serialization - implementation(libs.serializationJson) + implementation(libs.kotlin.serialization) // Retrofit api(libs.retrofit) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 363d9b1..1c44f2a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,16 +50,23 @@ agp = "8.7.3" kotlin = "2.0.0" ksp = "2.0.0-1.0.23" junitVersion = "1.2.1" +googleServicesPlugin = "4.4.2" # Matomo matomo = "4.3" -# Serialization -serialization = "1.7.1" - +# Compose navigation navigationCompose = "2.8.2" +# Crashlytics +firebaseCrashlyticsPlugin = "3.0.2" +firebaseCrashlyticsKtx = "19.2.0" +# Clarity +clarityVersion = "1.3.2" + +# GA4 +ga4 = "22.1.2" [libraries] @@ -91,9 +98,6 @@ compose-material3 = { group = "androidx.compose.material3", name = "material3" } # Material material = { group = "com.google.android.material", name = "material", version.ref = "material" } -# Matomo -matomo = { module = "com.github.matomo-org:matomo-sdk-android", version.ref = "matomo" } - # Kotlin serizalization kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" } @@ -105,9 +109,6 @@ androidx-navigation-compose = { group = "androidx.navigation", name = "navigatio # Preferences DataStore preferencesDataStore = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "preferencesDataStore" } -# Json serialization -serializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "jsonSerialization" } - # Retrofit retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } retrofitConverter = { group = "com.squareup.retrofit2", name = "converter-kotlinx-serialization", version.ref = "retrofit" } @@ -123,6 +124,15 @@ test-androidx-junit = { group = "androidx.test.ext", name = "junit-ktx", version test-espresso = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +# Matomo +matomo = { module = "com.github.matomo-org:matomo-sdk-android", version.ref = "matomo" } + +# Clarity +clarity = { group = "com.microsoft.clarity", name = "clarity", version.ref = "clarityVersion" } + +# GA4 (Firebase Analytics) +ga4 = { module = "com.google.firebase:firebase-analytics", version.ref = "ga4" } + [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } @@ -131,6 +141,8 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } android-library = { id = "com.android.library", version.ref = "agp" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "serialization" } +firebaseCrashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlyticsPlugin" } +googleServices = { id = "com.google.gms.google-services", version.ref = "googleServicesPlugin" } [bundles] androidx = ["androidx-core-ktx", "androidx-activity-compose"] From 2c4782b5c617c8cf33e60ff31385d36ddf3d431e Mon Sep 17 00:00:00 2001 From: Louis Legrand Date: Thu, 12 Dec 2024 09:26:54 +0100 Subject: [PATCH 2/2] =?UTF-8?q?feat(CON-173)=20:=20[SDK]=20-=20Module=20d'?= =?UTF-8?q?ex=C3=A9cution=20de=20code=20en=20fonction=20des=20consentement?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 - .../fr/openium/consentium/api/Consentium.kt | 98 +++++++++++++++++++ .../consentium/api/adapter/PurposeAdapter.kt | 12 +++ .../api/adapter/PurposeChoiceAdapter.kt | 10 ++ .../api/adapter/PurposeStatusAdapter.kt | 10 ++ .../consentium/api/adapter/VendorAdapter.kt | 11 +++ .../api/adapter/VendorChoiceAdapter.kt | 9 ++ .../openium/consentium/api/model/Purpose.kt | 8 ++ .../consentium/api/model/PurposeChoice.kt | 7 ++ .../consentium/api/model/PurposeIdentifier.kt | 24 +++++ .../consentium/api/model/PurposeStatus.kt | 8 ++ .../fr/openium/consentium/api/model/Vendor.kt | 7 ++ .../consentium/api/model/VendorChoice.kt | 6 ++ .../consentium/api/model/VendorIdentifier.kt | 30 ++++++ .../consentium/api/model/VendorStatus.kt | 7 ++ .../api/state/FetchConsentiumState.kt | 17 ++++ .../api/state/SetConsentiumState.kt | 13 +++ .../data/di/RepositoryEntryPoint.kt | 12 +++ .../consentium/data/remote/ConsentiumApi.kt | 6 +- .../data/remote/model/GetConsentPayloadDTO.kt | 4 +- .../data/repository/ConsentiumRepository.kt | 63 ++++++++++++ gradle/libs.versions.toml | 8 +- 22 files changed, 361 insertions(+), 10 deletions(-) create mode 100644 consentium/src/main/java/fr/openium/consentium/api/Consentium.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeAdapter.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeChoiceAdapter.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeStatusAdapter.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/adapter/VendorAdapter.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/adapter/VendorChoiceAdapter.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/Purpose.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/PurposeChoice.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/PurposeIdentifier.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/PurposeStatus.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/Vendor.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/VendorChoice.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/VendorIdentifier.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/model/VendorStatus.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/state/FetchConsentiumState.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/api/state/SetConsentiumState.kt create mode 100644 consentium/src/main/java/fr/openium/consentium/data/di/RepositoryEntryPoint.kt diff --git a/build.gradle.kts b/build.gradle.kts index a47fc9a..986ddcd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,5 +27,4 @@ plugins { // Google services alias(libs.plugins.googleServices) apply false - } \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/Consentium.kt b/consentium/src/main/java/fr/openium/consentium/api/Consentium.kt new file mode 100644 index 0000000..9427663 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/Consentium.kt @@ -0,0 +1,98 @@ +package fr.openium.consentium.api + +import android.content.Context +import dagger.hilt.android.EntryPointAccessors +import fr.openium.consentium.api.model.PurposeChoice +import fr.openium.consentium.api.model.PurposeIdentifier +import fr.openium.consentium.api.model.PurposeStatus +import fr.openium.consentium.api.model.VendorIdentifier +import fr.openium.consentium.api.model.VendorStatus +import fr.openium.consentium.api.state.FetchConsentiumState +import fr.openium.consentium.api.state.SetConsentiumState +import fr.openium.consentium.data.di.RepositoryEntryPoint +import fr.openium.consentium.data.repository.ConsentiumRepository +import fr.openium.consentium.data.repository.ConsentiumRepositoryGetResponse +import fr.openium.consentium.data.repository.ConsentiumRepositorySetResponse +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class Consentium( + context: Context, + val applicationId: String, +) { + private val _fetchConsentState = MutableStateFlow(FetchConsentiumState.Idle) + val fetchConsentState by lazy { _fetchConsentState.asStateFlow() } + + private val _setConsentState = MutableStateFlow(SetConsentiumState.Idle) + val setConsentState by lazy { _setConsentState.asStateFlow() } + + private val consentiumRepository: ConsentiumRepository by lazy { + val appContext = context.applicationContext + val entryPoint = EntryPointAccessors.fromApplication(appContext, RepositoryEntryPoint::class.java) + entryPoint.provideConsentiumRepository() + } + + fun getConsentStatus(purpose: PurposeIdentifier): PurposeStatus { + return when (val state = fetchConsentState.value) { + is FetchConsentiumState.Valid -> { + val purposeChoice = state.purposes.find { it.identifier == purpose } + purposeChoice?.isAccepted ?: PurposeStatus.UNKNOWN + } + + else -> PurposeStatus.UNKNOWN + } + } + + fun getConsentStatus(purpose: PurposeIdentifier, vendorIdentifier: VendorIdentifier): VendorStatus { + return when (val state = fetchConsentState.value) { + is FetchConsentiumState.Valid -> { + val vendorChoice = state.purposes.find { it.identifier == purpose } + ?.vendors?.find { it.identifier == vendorIdentifier } + + when (vendorChoice?.isAccepted) { + true -> VendorStatus.ACCEPTED + false -> VendorStatus.REJECTED + else -> VendorStatus.UNKNOWN + } + } + + else -> VendorStatus.UNKNOWN + } + } + + suspend fun fetchConsents() { + _fetchConsentState.value = FetchConsentiumState.Loading + try { + when (val consentResponse = consentiumRepository.getConsents(applicationId)) { + ConsentiumRepositoryGetResponse.Error -> _fetchConsentState.value = FetchConsentiumState.Error + + is ConsentiumRepositoryGetResponse.GetConsentsSuccess -> { + val areConsentsValid = consentResponse.isValid + if (areConsentsValid) { + _fetchConsentState.value = FetchConsentiumState.Valid(purposes = consentResponse.purposes) + } else { + _fetchConsentState.value = FetchConsentiumState.Invalid + } + } + } + + } catch (e: Exception) { + _fetchConsentState.value = FetchConsentiumState.Error + } + } + + suspend fun setConsents( + consent: List, + ) { + _setConsentState.value = SetConsentiumState.Loading + try { + when (consentiumRepository.setConsents(applicationId, consent)) { + ConsentiumRepositorySetResponse.Error -> _setConsentState.value = SetConsentiumState.Error + ConsentiumRepositorySetResponse.SetConsentsSuccess -> _setConsentState.value = SetConsentiumState.Success + } + + } catch (e: Exception) { + _setConsentState.value = SetConsentiumState.Error + } + } +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeAdapter.kt b/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeAdapter.kt new file mode 100644 index 0000000..f60776b --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeAdapter.kt @@ -0,0 +1,12 @@ +package fr.openium.consentium.api.adapter + +import fr.openium.consentium.api.model.Purpose +import fr.openium.consentium.api.model.PurposeIdentifier +import fr.openium.consentium.data.remote.model.GetConsent + +internal fun GetConsent.PurposeDTO.toPurpose() = Purpose( + identifier = PurposeIdentifier.fromString(identifier), + isRequired = isRequired, + isAccepted = isAccepted.toPurposeStatus(), + vendors = vendors?.map { it.toVendor() } ?: emptyList(), +) diff --git a/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeChoiceAdapter.kt b/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeChoiceAdapter.kt new file mode 100644 index 0000000..2babdd8 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeChoiceAdapter.kt @@ -0,0 +1,10 @@ +package fr.openium.consentium.api.adapter + +import fr.openium.consentium.api.model.PurposeChoice +import fr.openium.consentium.data.remote.model.PatchConsent + +internal fun PurposeChoice.toPatchConsentPurposeDTO() = PatchConsent.PurposeDTO( + identifier = purposeIdentifier.toString(), + isAccepted = isAccepted, + vendors = vendors.map { it.toPatchConsentVendorDTO() } +) \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeStatusAdapter.kt b/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeStatusAdapter.kt new file mode 100644 index 0000000..fc63bb5 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/adapter/PurposeStatusAdapter.kt @@ -0,0 +1,10 @@ +package fr.openium.consentium.api.adapter + +import fr.openium.consentium.api.model.PurposeStatus +import fr.openium.consentium.data.remote.model.GetConsent + +internal fun GetConsent.PurposeStatusDTO.toPurposeStatus() = when (this) { + GetConsent.PurposeStatusDTO.ACCEPTED -> PurposeStatus.ACCEPTED + GetConsent.PurposeStatusDTO.REJECTED -> PurposeStatus.REJECTED + GetConsent.PurposeStatusDTO.NOT_DEFINED -> PurposeStatus.NOT_DEFINED +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/adapter/VendorAdapter.kt b/consentium/src/main/java/fr/openium/consentium/api/adapter/VendorAdapter.kt new file mode 100644 index 0000000..b9c3bba --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/adapter/VendorAdapter.kt @@ -0,0 +1,11 @@ +package fr.openium.consentium.api.adapter + +import fr.openium.consentium.api.model.Vendor +import fr.openium.consentium.api.model.VendorIdentifier +import fr.openium.consentium.data.remote.model.GetConsent + +internal fun GetConsent.VendorDTO.toVendor() = Vendor( + identifier = VendorIdentifier.fromString(identifier), + isAccepted = isAccepted, + isRequired = isRequired, +) \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/adapter/VendorChoiceAdapter.kt b/consentium/src/main/java/fr/openium/consentium/api/adapter/VendorChoiceAdapter.kt new file mode 100644 index 0000000..ec76012 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/adapter/VendorChoiceAdapter.kt @@ -0,0 +1,9 @@ +package fr.openium.consentium.api.adapter + +import fr.openium.consentium.api.model.VendorChoice +import fr.openium.consentium.data.remote.model.PatchConsent + +internal fun VendorChoice.toPatchConsentVendorDTO() = PatchConsent.VendorDTO( + identifier = vendorIdentifier.toString(), + isAccepted = isAccepted, +) \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/Purpose.kt b/consentium/src/main/java/fr/openium/consentium/api/model/Purpose.kt new file mode 100644 index 0000000..6d9caab --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/Purpose.kt @@ -0,0 +1,8 @@ +package fr.openium.consentium.api.model + +data class Purpose( + val identifier: PurposeIdentifier, + val isRequired: Boolean, + val isAccepted: PurposeStatus, + val vendors: List, +) \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/PurposeChoice.kt b/consentium/src/main/java/fr/openium/consentium/api/model/PurposeChoice.kt new file mode 100644 index 0000000..bbd4c4a --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/PurposeChoice.kt @@ -0,0 +1,7 @@ +package fr.openium.consentium.api.model + +data class PurposeChoice( + val purposeIdentifier: PurposeIdentifier, + val isAccepted: Boolean, + val vendors: List, +) \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/PurposeIdentifier.kt b/consentium/src/main/java/fr/openium/consentium/api/model/PurposeIdentifier.kt new file mode 100644 index 0000000..3e3ce8f --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/PurposeIdentifier.kt @@ -0,0 +1,24 @@ +package fr.openium.consentium.api.model + +enum class PurposeIdentifier { + REQUIRED, + AUDIENCE, + ADS, + UNKNOWN; + + companion object { + fun fromString(string: String): PurposeIdentifier = when (string) { + "purpose-required" -> REQUIRED + "purpose-audience" -> AUDIENCE + "purpose-ads" -> ADS + else -> UNKNOWN + } + } + + override fun toString(): String = when (this) { + REQUIRED -> "purpose-required" + AUDIENCE -> "purpose-audience" + ADS -> "purpose-ads" + else -> "purpose-unknown" + } +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/PurposeStatus.kt b/consentium/src/main/java/fr/openium/consentium/api/model/PurposeStatus.kt new file mode 100644 index 0000000..6175e2a --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/PurposeStatus.kt @@ -0,0 +1,8 @@ +package fr.openium.consentium.api.model + +enum class PurposeStatus { + ACCEPTED, + REJECTED, + NOT_DEFINED, + UNKNOWN, +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/Vendor.kt b/consentium/src/main/java/fr/openium/consentium/api/model/Vendor.kt new file mode 100644 index 0000000..3499ae3 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/Vendor.kt @@ -0,0 +1,7 @@ +package fr.openium.consentium.api.model + +data class Vendor( + val identifier: VendorIdentifier, + val isAccepted: Boolean, + val isRequired: Boolean, +) \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/VendorChoice.kt b/consentium/src/main/java/fr/openium/consentium/api/model/VendorChoice.kt new file mode 100644 index 0000000..98681ab --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/VendorChoice.kt @@ -0,0 +1,6 @@ +package fr.openium.consentium.api.model + +data class VendorChoice( + val vendorIdentifier: VendorIdentifier, + val isAccepted: Boolean, +) \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/VendorIdentifier.kt b/consentium/src/main/java/fr/openium/consentium/api/model/VendorIdentifier.kt new file mode 100644 index 0000000..e5b4908 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/VendorIdentifier.kt @@ -0,0 +1,30 @@ +package fr.openium.consentium.api.model + +enum class VendorIdentifier { + CRASHLYTICS, + MATOMO, + GA4, + PIANO, + CLARITY, + UNKNOWN; + + companion object { + fun fromString(string: String): VendorIdentifier = when (string) { + "vendor-clarity" -> CLARITY + "vendor-crashlytics" -> CRASHLYTICS + "vendor-matomo" -> MATOMO + "vendor-ga4" -> GA4 + "vendor-piano" -> PIANO + else -> UNKNOWN + } + } + + override fun toString(): String = when (this) { + CLARITY -> "vendor-clarity" + CRASHLYTICS -> "vendor-crashlytics" + MATOMO -> "vendor-matomo" + GA4 -> "vendor-ga4" + PIANO -> "vendor-piano" + else -> "vendor-unknown" + } +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/model/VendorStatus.kt b/consentium/src/main/java/fr/openium/consentium/api/model/VendorStatus.kt new file mode 100644 index 0000000..43be282 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/model/VendorStatus.kt @@ -0,0 +1,7 @@ +package fr.openium.consentium.api.model + +enum class VendorStatus { + ACCEPTED, + REJECTED, + UNKNOWN, +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/state/FetchConsentiumState.kt b/consentium/src/main/java/fr/openium/consentium/api/state/FetchConsentiumState.kt new file mode 100644 index 0000000..2f08b0d --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/state/FetchConsentiumState.kt @@ -0,0 +1,17 @@ +package fr.openium.consentium.api.state + +import fr.openium.consentium.api.model.Purpose + +sealed interface FetchConsentiumState { + + data object Idle : FetchConsentiumState + + data object Loading : FetchConsentiumState + + data object Invalid : FetchConsentiumState + + data class Valid(val purposes: List) : FetchConsentiumState + + data object Error : FetchConsentiumState + +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/api/state/SetConsentiumState.kt b/consentium/src/main/java/fr/openium/consentium/api/state/SetConsentiumState.kt new file mode 100644 index 0000000..9f795b3 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/api/state/SetConsentiumState.kt @@ -0,0 +1,13 @@ +package fr.openium.consentium.api.state + +sealed interface SetConsentiumState { + + data object Idle : SetConsentiumState + + data object Loading : SetConsentiumState + + data object Success : SetConsentiumState + + data object Error : SetConsentiumState + +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/data/di/RepositoryEntryPoint.kt b/consentium/src/main/java/fr/openium/consentium/data/di/RepositoryEntryPoint.kt new file mode 100644 index 0000000..f39a140 --- /dev/null +++ b/consentium/src/main/java/fr/openium/consentium/data/di/RepositoryEntryPoint.kt @@ -0,0 +1,12 @@ +package fr.openium.consentium.data.di + +import dagger.hilt.EntryPoint +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import fr.openium.consentium.data.repository.ConsentiumRepository + +@EntryPoint +@InstallIn(SingletonComponent::class) +internal interface RepositoryEntryPoint { + fun provideConsentiumRepository(): ConsentiumRepository +} \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/data/remote/ConsentiumApi.kt b/consentium/src/main/java/fr/openium/consentium/data/remote/ConsentiumApi.kt index 4f3847d..8b70b47 100644 --- a/consentium/src/main/java/fr/openium/consentium/data/remote/ConsentiumApi.kt +++ b/consentium/src/main/java/fr/openium/consentium/data/remote/ConsentiumApi.kt @@ -2,6 +2,7 @@ package fr.openium.consentium.data.remote import fr.openium.consentium.data.remote.model.GetConsent import fr.openium.consentium.data.remote.model.PatchConsent +import retrofit2.Response import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.PATCH @@ -13,13 +14,12 @@ internal interface ConsentiumApi { suspend fun getConsents( applicationId: String, installationId: String, - ): GetConsent.GetConsentPayloadDTO + ): Response @PATCH("/consents") suspend fun setConsents( applicationId: String, - installationId: String, @Body patchConsent: PatchConsent.PatchConsentPayloadDTO, - ): Any + ): Response } \ No newline at end of file diff --git a/consentium/src/main/java/fr/openium/consentium/data/remote/model/GetConsentPayloadDTO.kt b/consentium/src/main/java/fr/openium/consentium/data/remote/model/GetConsentPayloadDTO.kt index 3206996..2bb7169 100644 --- a/consentium/src/main/java/fr/openium/consentium/data/remote/model/GetConsentPayloadDTO.kt +++ b/consentium/src/main/java/fr/openium/consentium/data/remote/model/GetConsentPayloadDTO.kt @@ -16,7 +16,7 @@ internal sealed interface GetConsent { data class PurposeDTO( @SerialName("identifier") val identifier: String, @SerialName("isRequired") val isRequired: Boolean, - @SerialName("isAccepted") val isAccepted: PurposeStatus, + @SerialName("isAccepted") val isAccepted: PurposeStatusDTO, @SerialName("vendors") val vendors: List? = null, ) @@ -28,7 +28,7 @@ internal sealed interface GetConsent { ) @Serializable - enum class PurposeStatus { + enum class PurposeStatusDTO { @SerialName("ACCEPTED") ACCEPTED, diff --git a/consentium/src/main/java/fr/openium/consentium/data/repository/ConsentiumRepository.kt b/consentium/src/main/java/fr/openium/consentium/data/repository/ConsentiumRepository.kt index f553d83..1674025 100644 --- a/consentium/src/main/java/fr/openium/consentium/data/repository/ConsentiumRepository.kt +++ b/consentium/src/main/java/fr/openium/consentium/data/repository/ConsentiumRepository.kt @@ -1,7 +1,12 @@ package fr.openium.consentium.data.repository +import fr.openium.consentium.api.adapter.toPatchConsentPurposeDTO +import fr.openium.consentium.api.adapter.toPurpose +import fr.openium.consentium.api.model.Purpose +import fr.openium.consentium.api.model.PurposeChoice import fr.openium.consentium.data.local.ConsentiumDataStore import fr.openium.consentium.data.remote.ConsentiumApi +import fr.openium.consentium.data.remote.model.PatchConsent import javax.inject.Inject internal class ConsentiumRepository @Inject constructor( @@ -9,5 +14,63 @@ internal class ConsentiumRepository @Inject constructor( private val consentiumDataStore: ConsentiumDataStore, ) { + suspend fun getConsents(applicationId: String): ConsentiumRepositoryGetResponse { + val installationId = consentiumDataStore.getInstallationUniqueId() + val consentsResponse = consentiumApi.getConsents(applicationId, installationId) + return try { + val consentsBody = if (consentsResponse.isSuccessful) { + consentsResponse.body() ?: throw Exception() + } else { + throw Exception() + } + + return ConsentiumRepositoryGetResponse.GetConsentsSuccess( + isValid = consentsBody.isValid, + purposes = consentsBody.purposes?.map { purpose -> purpose.toPurpose() } ?: emptyList() + ) + } catch (e: Exception) { + ConsentiumRepositoryGetResponse.Error + } + } + + suspend fun setConsents( + applicationId: String, + consents: List, + ): ConsentiumRepositorySetResponse { + val installationId = consentiumDataStore.getInstallationUniqueId() + + val setConsentResponse = consentiumApi.setConsents( + applicationId = applicationId, + patchConsent = PatchConsent.PatchConsentPayloadDTO( + installationId = installationId, + purposes = consents.map { it.toPatchConsentPurposeDTO() }, + ) + ) + + return if (setConsentResponse.isSuccessful) { + ConsentiumRepositorySetResponse.SetConsentsSuccess + } else { + ConsentiumRepositorySetResponse.Error + } + } + +} + +internal interface ConsentiumRepositoryGetResponse { + + data object Error : ConsentiumRepositoryGetResponse + + data class GetConsentsSuccess( + val isValid: Boolean, + val purposes: List, + ) : ConsentiumRepositoryGetResponse + +} + +internal interface ConsentiumRepositorySetResponse { + + data object Error : ConsentiumRepositorySetResponse + + data object SetConsentsSuccess : ConsentiumRepositorySetResponse } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1c44f2a..97650ee 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,8 +27,8 @@ timber = "5.0.1" material = "1.12.0" # Serialization -serialization = "2.0.21" -jsonSerialization = "1.7.3" +serialization = "2.0.0" +jsonSerialization = "1.7.1" # Retrofit retrofit = "2.11.0" @@ -48,7 +48,7 @@ preferencesDataStore = "1.1.1" # Plugins agp = "8.7.3" kotlin = "2.0.0" -ksp = "2.0.0-1.0.23" +ksp = "2.0.0-1.0.24" junitVersion = "1.2.1" googleServicesPlugin = "4.4.2" @@ -99,7 +99,7 @@ compose-material3 = { group = "androidx.compose.material3", name = "material3" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } # Kotlin serizalization -kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" } +kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "jsonSerialization" } # Compose navigation androidx-navigation-common-ktx = { group = "androidx.navigation", name = "navigation-common-ktx", version.ref = "navigationCompose" }