feat(CON-265) : Aligner les flux de l'api d'UI avec les nouveaux dev back

This commit is contained in:
Louis Legrand 2025-02-11 17:00:53 +01:00
parent c57c9b7d05
commit af91841857
36 changed files with 144 additions and 176 deletions

View File

@ -3,12 +3,14 @@ import androidx.compose.animation.slideIn
import androidx.compose.animation.slideOut
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.IntOffset
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.toRoute
import fr.openium.consentium.R
import fr.openium.consentium.api.Consentium
import fr.openium.consentium.ui.screens.main.MainScreen
import fr.openium.consentium.ui.screens.splash.SplashScreen
@ -79,6 +81,9 @@ fun DemoNavGraph(navHostController: NavHostController) {
composable<Destination.Consent> { backStackEntry ->
val consent = backStackEntry.toRoute<Destination.Consent>()
val appId = stringResource(R.string.app_id)
val apiKey = stringResource(R.string.api_key)
val context = LocalContext.current
ConsentiumComponent(
defaultLandingPage = consent.landingPage,
@ -91,7 +96,8 @@ fun DemoNavGraph(navHostController: NavHostController) {
},
consentium = Consentium(
context = context,
applicationId = "ApplicationId",
apiKey = apiKey,
appId = appId,
),
colors = ConsentiumDefaults.colors(
primary = Primary,

View File

@ -27,8 +27,9 @@ fun SplashScreen(
) {
// Property
val context = LocalContext.current
val consentiumKey = stringResource(R.string.consentium_api_key)
val consentium = remember { Consentium(context = context, applicationId = consentiumKey) }
val apiKey = stringResource(R.string.api_key)
val appId = stringResource(R.string.app_id)
val consentium = remember { Consentium(context = context, apiKey = apiKey, appId = appId) }
// Effect
LaunchedEffect(Unit) {

View File

@ -1,4 +1,5 @@
<resources>
<string name="app_name">Consentium</string>
<string translatable="false" name="consentium_api_key">01938ce4-331a-7592-9e90-f09201ff4f36</string>
<string name="app_id" translatable="false">01938ce4-331a-7592-9e90-f09201ff4f36</string>
<string name="api_key" translatable="false">c452a27f-2e90-427d-be82-2f631c31dd09</string>
</resources>

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -3,13 +3,15 @@ package fr.openium.consentium_ui.data.remote
import fr.openium.consentium_ui.data.remote.model.GetConsentConfigDTO
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Path
internal interface ConsentiumUIApi {
@GET("consent-config")
@GET("applications/{application}")
suspend fun getConsentConfig(
applicationID: String,
installationID: String,
@Header("Authorization") token: String,
@Path("application") applicationId: String,
): Response<GetConsentConfigDTO>
}

View File

@ -6,8 +6,6 @@ import fr.openium.consentium_ui.data.remote.model.MainConsentTextTranslationDTO
import fr.openium.consentium_ui.data.remote.model.PurposeDTO
import fr.openium.consentium_ui.data.remote.model.PurposeStatusDTO
import fr.openium.consentium_ui.data.remote.model.PurposeTranslationDTO
import fr.openium.consentium_ui.data.remote.model.VendorDTO
import fr.openium.consentium_ui.data.remote.model.VendorTranslationDTO
import retrofit2.Response
import java.util.UUID
@ -17,9 +15,6 @@ internal object ConsentiumUIMockApi : ConsentiumUIApi {
installationId = UUID.randomUUID().toString(),
appName = "Consentium",
icon = "https://amp.openium.fr/openium.png",
primaryColor = "#FF0000",
secondaryColor = "#00FF00",
textColor = "#0000FF",
consentMainTextTranslation = listOf(
MainConsentTextTranslationDTO(
id = "UUID",
@ -29,12 +24,13 @@ internal object ConsentiumUIMockApi : ConsentiumUIApi {
durationText = "<p>Nous conservons votre choix pendant 12 mois. Vous pouvez changer davis à tout moment depuis les paramètres de votre compte via longlet “Notification et cookies” tetetettetettetetstts</p>\n"
)
),
consentPageUrl = "https://www.openium.fr",
purposes = listOf(
PurposeDTO(
id = "purpose-required",
order = 0,
isRequired = true,
isAccepted = PurposeStatusDTO.ACCEPTED,
choice = PurposeStatusDTO.ACCEPTED,
translations = listOf(
PurposeTranslationDTO(
id = "UUID",
@ -43,40 +39,12 @@ internal object ConsentiumUIMockApi : ConsentiumUIApi {
name = "Nécessaire"
)
),
vendors = listOf(
VendorDTO(
id = "vendors-crashlytics",
order = 0,
isAccepted = true,
isRequired = true,
translations = listOf(
VendorTranslationDTO(
id = "UUID",
language = "fr",
text = "<p>Ces traceurs sont nécessaire au fonctionnement de lapplication. Ils permettent de vérifier la stabilité technique de lapplication et de mesurer notre audience. Ces données ne sont utilisées que pour notre compte exclusif (en ne produisant que des données statistiques anonymes).</p>"
)
)
),
VendorDTO(
id = "vendors-matomo",
order = 1,
isAccepted = true,
isRequired = false,
translations = listOf(
VendorTranslationDTO(
id = "UUID",
language = "fr",
text = "<p>Ces traceurs sont nécessaire au fonctionnement de lapplication. Ils permettent de vérifier la stabilité technique de lapplication et de mesurer notre audience. Ces données ne sont utilisées que pour notre compte exclusif (en ne produisant que des données statistiques anonymes).</p>"
)
)
)
)
),
PurposeDTO(
id = "purpose-advertising",
order = 1,
isRequired = false,
isAccepted = PurposeStatusDTO.REJECTED,
choice = PurposeStatusDTO.REFUSED,
translations = listOf(
PurposeTranslationDTO(
id = "UUID",
@ -85,27 +53,12 @@ internal object ConsentiumUIMockApi : ConsentiumUIApi {
name = "Publicité"
)
),
vendors = listOf(
VendorDTO(
id = "vendors-admob",
order = 0,
isAccepted = true,
isRequired = false,
translations = listOf(
VendorTranslationDTO(
id = "UUID",
language = "fr",
text = "<p>Ces traceurs sont nécessaires pour afficher des publicités susceptibles de vous intéresser. Ils permettent de mesurer lefficacité de nos campagnes publicitaires et de personnaliser les publicités affichées.</p>"
)
)
)
)
),
PurposeDTO(
id = "purpose-analytics",
order = 2,
isRequired = false,
isAccepted = PurposeStatusDTO.ACCEPTED,
choice = PurposeStatusDTO.ACCEPTED,
translations = listOf(
PurposeTranslationDTO(
id = "UUID",
@ -114,27 +67,12 @@ internal object ConsentiumUIMockApi : ConsentiumUIApi {
name = "Analyse"
)
),
vendors = listOf(
VendorDTO(
id = "vendors-firebase",
order = 0,
isAccepted = true,
isRequired = false,
translations = listOf(
VendorTranslationDTO(
id = "UUID",
language = "fr",
text = "<p>Ces traceurs sont nécessaires pour mesurer lefficacité de nos contenus. Ils permettent de mesurer laudience de lapplication et de comprendre comment les utilisateurs interagissent avec lapplication.</p>"
)
)
)
)
),
PurposeDTO(
id = "purpose-personalization",
order = 3,
isRequired = false,
isAccepted = PurposeStatusDTO.ACCEPTED,
choice = PurposeStatusDTO.ACCEPTED,
translations = listOf(
PurposeTranslationDTO(
id = "UUID",
@ -143,27 +81,12 @@ internal object ConsentiumUIMockApi : ConsentiumUIApi {
name = "Personnalisation"
)
),
vendors = listOf(
VendorDTO(
id = "vendors-firebase",
order = 0,
isAccepted = true,
isRequired = false,
translations = listOf(
VendorTranslationDTO(
id = "UUID",
language = "fr",
text = "<p>Ces traceurs sont nécessaires pour mesurer lefficacité de nos contenus. Ils permettent de mesurer laudience de lapplication et de comprendre comment les utilisateurs interagissent avec lapplication.</p>"
)
)
)
)
),
PurposeDTO(
id = "purpose-social",
order = 4,
isRequired = false,
isAccepted = PurposeStatusDTO.ACCEPTED,
choice = PurposeStatusDTO.ACCEPTED,
translations = listOf(
PurposeTranslationDTO(
id = "UUID",
@ -172,28 +95,13 @@ internal object ConsentiumUIMockApi : ConsentiumUIApi {
name = "Social"
)
),
vendors = listOf(
VendorDTO(
id = "vendors-firebase",
order = 0,
isAccepted = true,
isRequired = false,
translations = listOf(
VendorTranslationDTO(
id = "UUID",
language = "fr",
text = "<p>Ces traceurs sont nécessaires pour mesurer lefficacité de nos contenus. Ils permettent de mesurer laudience de lapplication et de comprendre comment les utilisateurs interagissent avec lapplication.</p>"
)
)
)
)
)
)
)
override suspend fun getConsentConfig(
applicationID: String,
installationID: String,
token: String,
applicationId: String,
): Response<GetConsentConfigDTO> {
return Response.success(consents)
}

View File

@ -7,10 +7,8 @@ import kotlinx.serialization.Serializable
internal data class GetConsentConfigDTO(
@SerialName("id") val installationId: String,
@SerialName("name") val appName: String,
@SerialName("icon") val icon: String,
@SerialName("primaryColor") val primaryColor: String,
@SerialName("secondaryColor") val secondaryColor: String,
@SerialName("textColor") val textColor: String,
@SerialName("translation") val consentMainTextTranslation: List<MainConsentTextTranslationDTO>,
@SerialName("icon") val icon: String? = null,
@SerialName("consentPageUrl") val consentPageUrl: String,
@SerialName("translations") val consentMainTextTranslation: List<MainConsentTextTranslationDTO>,
@SerialName("purposes") val purposes: List<PurposeDTO>,
)

View File

@ -7,7 +7,8 @@ import kotlinx.serialization.Serializable
internal data class MainConsentTextTranslationDTO(
@SerialName("id") val id: String,
@SerialName("lang") val language: String,
@SerialName("consentPageUrl") val consentPageUrl: String,
@SerialName("mainConsentText") val mainConsentText: String,
@SerialName("durationText") val durationText: String,
@SerialName("consentPageUrl") val consentPageUrl: String,
)

View File

@ -5,10 +5,10 @@ import kotlinx.serialization.Serializable
@Serializable
internal data class PurposeDTO(
@SerialName("identifier") val id: String,
@SerialName("order") val order: Int,
@SerialName("sortOrder") val order: Int,
@SerialName("isRequired") val isRequired: Boolean,
@SerialName("isAccepted") val isAccepted: PurposeStatusDTO,
@SerialName("choice") val choice: PurposeStatusDTO,
@SerialName("translations") val translations: List<PurposeTranslationDTO>,
@SerialName("vendors") val vendors: List<VendorDTO>,
@SerialName("identifier") val id: String,
)

View File

@ -5,12 +5,12 @@ import kotlinx.serialization.Serializable
@Serializable
internal enum class PurposeStatusDTO {
@SerialName("ACCEPTED")
@SerialName("accepted")
ACCEPTED,
@SerialName("REJECTED")
REJECTED,
@SerialName("refused")
REFUSED,
@SerialName("NOT_DEFINED")
NOT_DEFINED,
@SerialName("partial")
PARTIAL,
}

View File

@ -7,9 +7,9 @@ internal fun PurposeDTO.toPurposeData() =
PurposeData(
identifier = id,
isRequired = isRequired,
isAccepted = isAccepted.toPurposeStatusData(),
choice = choice.toPurposeStatusData(),
order = order,
vendors = vendors.toVendorDataList(),
vendors = emptyList(),
translations = translations.toPurposeTranslationDataList(),
)

View File

@ -6,7 +6,7 @@ import fr.openium.consentium_ui.domain.model.PurposeStatusData
internal fun PurposeStatusDTO.toPurposeStatusData(): PurposeStatusData {
return when (this) {
PurposeStatusDTO.ACCEPTED -> PurposeStatusData.ACCEPTED
PurposeStatusDTO.REJECTED -> PurposeStatusData.REJECTED
PurposeStatusDTO.NOT_DEFINED -> PurposeStatusData.NOT_DEFINED
PurposeStatusDTO.REFUSED -> PurposeStatusData.REJECTED
PurposeStatusDTO.PARTIAL -> PurposeStatusData.PARTIAL
}
}

View File

@ -2,7 +2,7 @@ package fr.openium.consentium_ui.domain.model
internal data class ContentConfigData(
val applicationName: String,
val iconUrl : String,
val iconUrl : String?,
val mainTextTranslation: List<MainConsentTextTranslationData>,
val purposes: List<PurposeData>
)

View File

@ -4,7 +4,7 @@ internal data class PurposeData(
val identifier: String,
val order: Int,
val isRequired: Boolean,
val isAccepted: PurposeStatusData,
val choice: PurposeStatusData,
val translations: List<PurposeTranslationData>,
val vendors: List<VendorData>,
)

View File

@ -3,5 +3,5 @@ package fr.openium.consentium_ui.domain.model
internal enum class PurposeStatusData {
ACCEPTED,
REJECTED,
NOT_DEFINED,
PARTIAL,
}

View File

@ -1,22 +1,23 @@
package fr.openium.consentium_ui.domain.repository
import fr.openium.consentium.domain.useCase.GetConsentiumUniqueInstallationIdUseCase
import fr.openium.consentium.domain.useCase.GetAuthTokenUseCase
import fr.openium.consentium_ui.data.remote.ConsentiumUIApi
import fr.openium.consentium_ui.domain.adapter.toConsentConfigData
import fr.openium.consentium_ui.domain.model.ContentConfigData
import timber.log.Timber
import javax.inject.Inject
internal class ConsentiumRepository @Inject constructor(
private val getConsentiumUniqueInstallationIdUseCase: GetConsentiumUniqueInstallationIdUseCase,
private val consentiumUIApi: ConsentiumUIApi,
private val getAuthTokenUseCase: GetAuthTokenUseCase,
) {
suspend fun getConsentiumConfig(
applicationId: String,
apiKey: String,
): ConsentiumUIRepositoryResponse {
val installationId = getConsentiumUniqueInstallationIdUseCase.invoke()
val consentsResponse = consentiumUIApi.getConsentConfig(applicationId, installationId)
return try {
val authToken = getAuthTokenUseCase(apiKey)
val consentsResponse = consentiumUIApi.getConsentConfig(authToken, applicationId)
val consentsBody = if (consentsResponse.isSuccessful) {
consentsResponse.body() ?: throw Exception()
} else {
@ -25,10 +26,10 @@ internal class ConsentiumRepository @Inject constructor(
ConsentiumUIRepositoryResponse.Success(consentsBody.toConsentConfigData())
} catch (e: Exception) {
Timber.d("$e")
ConsentiumUIRepositoryResponse.Error
}
}
}
internal interface ConsentiumUIRepositoryResponse {

View File

@ -27,6 +27,7 @@ internal fun ConsentiumScreen(
onSaveAndCloseDetails: (consents: DetailConsentUI) -> Unit,
onNavigateToDetails: () -> Unit,
onClickCookiesPolicies: () -> Unit,
onClickRetry: () -> Unit,
) {
when (state) {
is ConsentiumUIState.Loading -> {
@ -36,6 +37,7 @@ internal fun ConsentiumScreen(
is ConsentiumUIState.Error -> {
ConsentiumUIErrorComponent(
errorMessage = state.message,
onRetry = onClickRetry
)
}

View File

@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import fr.openium.consentium_ui.R
import fr.openium.consentium_ui.domain.repository.ConsentiumRepository
import fr.openium.consentium_ui.domain.repository.ConsentiumUIRepositoryResponse
import fr.openium.consentium_ui.domain.usecase.GetApplicationLanguageUseCase
@ -30,12 +31,12 @@ internal class ConsentiumUIViewModel @Inject constructor(
private val _state = MutableStateFlow<ConsentiumUIState>(ConsentiumUIState.Loading)
val state: StateFlow<ConsentiumUIState> by lazy { _state.asStateFlow() }
fun init(appId: String) {
fun init(appId: String, apiKey: String) {
viewModelScope.launch {
_state.value = ConsentiumUIState.Loading
when (val consentiumUIFetchResponse = consentiumUIRepository.getConsentiumConfig(appId)) {
when (val consentiumUIFetchResponse = consentiumUIRepository.getConsentiumConfig(appId, apiKey)) {
is ConsentiumUIRepositoryResponse.Success -> {
val consentUIResponse =
@ -44,28 +45,32 @@ internal class ConsentiumUIViewModel @Inject constructor(
when (val consentUI = consentUIResponse) {
is GetConfigTextForLanguageUseCaseResponse.Success -> {
_state.emit(ConsentiumUIState.Loaded(
_state.emit(
ConsentiumUIState.Loaded(
generalConsentUI = consentUI.configData.toGeneralConsentUI(),
detailConsentUI = consentUI.configData.toDetailConsentUI(),
))
)
)
}
is GetConfigTextForLanguageUseCaseResponse.DefaultLanguage -> {
_state.emit(ConsentiumUIState.Loaded(
_state.emit(
ConsentiumUIState.Loaded(
generalConsentUI = consentUI.configData.toGeneralConsentUI(),
detailConsentUI = consentUI.configData.toDetailConsentUI(),
))
)
)
}
is GetConfigTextForLanguageUseCaseResponse.Error -> {
_state.emit(ConsentiumUIState.Error("Failed to load data"))
_state.emit(ConsentiumUIState.Error(context.getString(R.string.consents_error_loading_consents)))
}
}
}
is ConsentiumUIRepositoryResponse.Error -> {
_state.value = ConsentiumUIState.Error("Failed to load data")
_state.value = ConsentiumUIState.Error(context.getString(R.string.consents_error_loading_consents))
}
}

View File

@ -1,6 +1,7 @@
package fr.openium.consentium_ui.ui.adapter
import fr.openium.consentium.api.model.PurposeChoice
import fr.openium.consentium.api.model.PurposeStatus
import fr.openium.consentium_ui.domain.model.ContentConfigData
import fr.openium.consentium_ui.ui.model.DetailConsentUI
import fr.openium.consentium_ui.ui.model.PurposeStatusUI
@ -17,16 +18,23 @@ internal fun DetailConsentUI.toPurposeChoices(): List<PurposeChoice> = purposes.
}
internal fun DetailConsentUI.toDeniedPurposeChoices(): List<PurposeChoice> = purposes.map {
it.toPurposeChoice().copy(isAccepted = false)
it.toPurposeChoice().copy(choice = PurposeStatus.REJECTED)
}
internal fun DetailConsentUI.toAcceptedPurposeChoices(): List<PurposeChoice> = purposes.map {
it.toPurposeChoice().copy(isAccepted = true)
it.toPurposeChoice().copy(choice = PurposeStatus.ACCEPTED)
}
internal fun PurposeUI.toPurposeChoice(): PurposeChoice =
PurposeChoice(
purposeIdentifier = id,
isAccepted = isAccepted == PurposeStatusUI.ACCEPTED,
choice = choice.toPurposeStatus(),
vendors = emptyList(), // Not in v1
)
internal fun PurposeStatusUI.toPurposeStatus(): PurposeStatus =
when (this) {
PurposeStatusUI.ACCEPTED -> PurposeStatus.ACCEPTED
PurposeStatusUI.REJECTED -> PurposeStatus.REJECTED
PurposeStatusUI.PARTIAL -> PurposeStatus.PARTIAL
}

View File

@ -6,5 +6,5 @@ import fr.openium.consentium_ui.ui.model.PurposeStatusUI
internal fun PurposeStatusData.toPurposeStatusUI(): PurposeStatusUI = when(this) {
PurposeStatusData.ACCEPTED -> PurposeStatusUI.ACCEPTED
PurposeStatusData.REJECTED -> PurposeStatusUI.REJECTED
PurposeStatusData.NOT_DEFINED -> PurposeStatusUI.NOT_DEFINED
PurposeStatusData.PARTIAL -> PurposeStatusUI.PARTIAL
}

View File

@ -6,7 +6,7 @@ import fr.openium.consentium_ui.ui.model.PurposeUI
internal fun PurposeData.toPurposeUI(): PurposeUI = PurposeUI(
id = identifier,
isRequired = isRequired,
isAccepted = isAccepted.toPurposeStatusUI(),
choice = choice.toPurposeStatusUI(),
title = translations.first().name,
description = translations.first().text,
vendors = vendors.toVendorUIList(),

View File

@ -51,7 +51,7 @@ fun ConsentiumComponent(
// Effect
LaunchedEffect(Unit) {
viewModel.init(consentium.applicationId)
viewModel.init(apiKey = consentium.apiKey, appId = consentium.appId)
}
LaunchedEffect(consentiumState) {
@ -131,6 +131,9 @@ fun ConsentiumComponent(
onClickCookiesPolicies = {
currentPage = ConsentiumPageUI.COOKIES_POLICY
},
onClickRetry = {
viewModel.init(apiKey = consentium.apiKey, appId = consentium.appId)
}
)
}
}

View File

@ -2,19 +2,31 @@ package fr.openium.consentium_ui.ui.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import fr.openium.consentium_ui.R
import fr.openium.consentium_ui.ui.components.core.button.ConsentButton
import fr.openium.consentium_ui.ui.components.core.button.ConsentiumUIButtonStyle
import fr.openium.consentium_ui.ui.components.style.ConsentiumUITheme
@Composable
internal fun ConsentiumUIErrorComponent(
errorMessage: String,
onRetry: () -> Unit,
) {
Column(
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 24.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
@ -22,6 +34,15 @@ internal fun ConsentiumUIErrorComponent(
text = errorMessage,
color = ConsentiumUITheme.colors.error,
style = ConsentiumUITheme.typography.b2,
textAlign = TextAlign.Center,
)
Spacer(modifier = Modifier.height(24.dp))
ConsentButton(
text = stringResource(R.string.retry),
buttonStyle = ConsentiumUIButtonStyle.PRIMARY,
onclick = onRetry,
)
}
}

View File

@ -28,7 +28,7 @@ internal fun PurposeComponent(
purposeUI: PurposeUI,
) {
// Properties
var isChecked by remember { mutableStateOf(purposeUI.isAccepted != PurposeStatusUI.REJECTED) }
var isChecked by remember { mutableStateOf(purposeUI.choice != PurposeStatusUI.REJECTED) }
// View
Column(
@ -58,7 +58,7 @@ internal fun PurposeComponent(
checked = isChecked,
onCheckedChange = {
isChecked = !isChecked
purposeUI.isAccepted = if (isChecked) PurposeStatusUI.ACCEPTED else PurposeStatusUI.REJECTED
purposeUI.choice = if (isChecked) PurposeStatusUI.ACCEPTED else PurposeStatusUI.REJECTED
purposeUI.vendors.forEach { vendorUI ->
vendorUI.isAccepted = isChecked
}
@ -95,7 +95,7 @@ private fun PurposeComponentPreview() {
purposeUI = PurposeUI(
id = "1",
isRequired = true,
isAccepted = PurposeStatusUI.ACCEPTED,
choice = PurposeStatusUI.ACCEPTED,
title = "Title",
description = "Description",
vendors = emptyList(),

View File

@ -2,7 +2,7 @@ package fr.openium.consentium_ui.ui.model
internal data class GeneralConsentUI(
val applicationName: String,
val iconUrl: String,
val iconUrl: String?,
val mainConsentText: String,
val consentPageUrl: String,
)

View File

@ -3,5 +3,5 @@ package fr.openium.consentium_ui.ui.model
internal enum class PurposeStatusUI {
ACCEPTED,
REJECTED,
NOT_DEFINED,
PARTIAL,
}

View File

@ -3,7 +3,7 @@ package fr.openium.consentium_ui.ui.model
internal data class PurposeUI(
val id: String,
val isRequired: Boolean,
var isAccepted: PurposeStatusUI,
var choice: PurposeStatusUI,
val title: String,
val description: String,
val vendors: List<VendorUI>,

View File

@ -6,5 +6,7 @@
<string name="parameters">Paramétrer mes choix</string>
<string name="save">Enregistrer et fermer</string>
<string name="require">Requis</string>
<string name="retry">Réessayer</string>
<string name="save_consents_error_message">Une erreur est survenue l\'or de la ssauvegarde de vos consentements.</string>
<string name="consents_error_loading_consents">Il y a eu une erreur lors du chargement de vos consentements</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="backend_url" translatable="false" tools:ignore="UnusedResources">https://consentium-api-dev.openium.fr/api/v1/app</string>
<resources>
<string name="backend_url" translatable="false">https://consentium-api-dev.openium.fr/api/v1/app/</string>
</resources>

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -15,7 +15,8 @@ import kotlinx.coroutines.flow.asStateFlow
class Consentium(
context: Context,
val applicationId: String,
val apiKey: String,
val appId: String,
) {
private val _fetchConsentState = MutableStateFlow<FetchConsentiumState>(FetchConsentiumState.Idle)
val fetchConsentState by lazy { _fetchConsentState.asStateFlow() }
@ -32,7 +33,7 @@ class Consentium(
suspend fun fetchConsents() {
_fetchConsentState.value = FetchConsentiumState.Loading
try {
when (val consentResponse = consentiumRepository.getConsents(applicationId)) {
when (val consentResponse = consentiumRepository.getConsents(apiKey)) {
ConsentiumRepositoryGetResponse.Error -> _fetchConsentState.value = FetchConsentiumState.Error
is ConsentiumRepositoryGetResponse.GetConsentsSuccess -> {
@ -54,7 +55,7 @@ class Consentium(
) {
_saveConsentState.emit(SetConsentiumState.Loading)
try {
when (consentiumRepository.setConsents(applicationId, consent)) {
when (consentiumRepository.setConsents(apiKey, consent)) {
ConsentiumRepositorySetResponse.Error -> {
_saveConsentState.emit(SetConsentiumState.Error)
}

View File

@ -11,12 +11,12 @@ import retrofit2.http.POST
internal interface ConsentiumApi {
@GET("/consents")
@GET("consents")
suspend fun getConsents(
@Header("Authorization") token: String,
): Response<GetConsent.GetConsentPayloadDTO>
@POST("/consents")
@POST("consents")
suspend fun setConsents(
@Header("Authorization") token: String,
@Body patchConsent: PatchConsent.PatchConsentPayloadDTO,

View File

@ -7,7 +7,7 @@ internal sealed interface GetConsent {
@Serializable
data class GetConsentPayloadDTO(
@SerialName("id") val id: String,
@SerialName("id") val id: String? = null,
@SerialName("installationId") val installationId: String,
@SerialName("state") val state: ConsentStateDTO? = null,
@SerialName("acceptedDate") val acceptedData: Long? = null,

View File

@ -16,10 +16,11 @@ internal class ConsentiumRepository @Inject constructor(
private val getAuthTokenUseCase: GetAuthTokenUseCase,
) {
suspend fun getConsents(applicationId: String): ConsentiumRepositoryGetResponse {
val authToken = getAuthTokenUseCase(applicationId)
val consentsResponse = consentiumApi.getConsents(authToken)
suspend fun getConsents(apiKey: String): ConsentiumRepositoryGetResponse {
return try {
val authToken = getAuthTokenUseCase(apiKey)
val consentsResponse = consentiumApi.getConsents(authToken)
val consentsBody = if (consentsResponse.isSuccessful) {
consentsResponse.body() ?: throw Exception()
} else {

View File

@ -5,7 +5,7 @@ import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
interface GetAuthTokenUseCase {
suspend operator fun invoke(applicationId: String): String
suspend operator fun invoke(apiKey: String): String
}
class GetAuthTokenUseCaseImpl @Inject internal constructor(
@ -13,11 +13,11 @@ class GetAuthTokenUseCaseImpl @Inject internal constructor(
) : GetAuthTokenUseCase {
@OptIn(ExperimentalEncodingApi::class)
override suspend operator fun invoke(applicationId: String): String {
override suspend operator fun invoke(apiKey: String): String {
val uniqueInstallationId = getConsentiumUniqueInstallationIdUseCase()
val clearToken = "$applicationId.$uniqueInstallationId"
val clearToken = "$apiKey.$uniqueInstallationId"
val cipheredToken = Base64.Default.encode(clearToken.toByteArray())
return "Bearer $cipheredToken"
return "Basic $cipheredToken"
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="backend_url" translatable="false" tools:ignore="UnusedResources">https://consentium-api.openium.fr/api/v1/app/</string>
</resources>