From 8268077bd353979c20abdda1344cc4eefdf0239b Mon Sep 17 00:00:00 2001 From: STYLIATIS Stamatis Date: Fri, 15 Nov 2024 12:56:14 +0200 Subject: [PATCH 01/10] Added document Sign screen, viewmodel and interactor to open file selection --- .../di/FeatureDashboardModule.kt | 10 +- .../interactor/DocumentSignInteractor.kt | 34 ++++ .../ec/dashboardfeature/router/Graph.kt | 7 + .../ui/dashboard/DashboardViewModel.kt | 20 +++ .../ui/sign/DocumentSignScreen.kt | 168 ++++++++++++++++++ .../ui/sign/DocumentSignViewModel.kt | 81 +++++++++ .../main/res/drawable/ic_sign_document.xml | 9 + .../src/main/res/values/strings.xml | 6 + .../europa/ec/uilogic/component/AppIcons.kt | 6 + .../ec/uilogic/navigation/RouterContract.kt | 2 + 10 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt create mode 100644 dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt create mode 100644 dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt create mode 100644 resources-logic/src/main/res/drawable/ic_sign_document.xml diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/di/FeatureDashboardModule.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/di/FeatureDashboardModule.kt index ff70f9a4..b93aabb3 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/di/FeatureDashboardModule.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/di/FeatureDashboardModule.kt @@ -22,6 +22,8 @@ import eu.europa.ec.corelogic.config.WalletCoreConfig import eu.europa.ec.corelogic.controller.WalletCoreDocumentsController import eu.europa.ec.dashboardfeature.interactor.DashboardInteractor import eu.europa.ec.dashboardfeature.interactor.DashboardInteractorImpl +import eu.europa.ec.dashboardfeature.interactor.DocumentSignInteractor +import eu.europa.ec.dashboardfeature.interactor.DocumentSignInteractorImpl import eu.europa.ec.resourceslogic.provider.ResourceProvider import org.koin.core.annotation.ComponentScan import org.koin.core.annotation.Factory @@ -37,7 +39,7 @@ fun provideDashboardInteractor( walletCoreDocumentsController: WalletCoreDocumentsController, walletCoreConfig: WalletCoreConfig, configLogic: ConfigLogic, - logController: LogController + logController: LogController, ): DashboardInteractor = DashboardInteractorImpl( resourceProvider, @@ -45,4 +47,8 @@ fun provideDashboardInteractor( walletCoreConfig, configLogic, logController - ) \ No newline at end of file + ) + +@Factory +fun provideDocumentSignInteractor(): DocumentSignInteractor = + DocumentSignInteractorImpl() \ No newline at end of file diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt new file mode 100644 index 00000000..861643cb --- /dev/null +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 European Commission + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work + * except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific language + * governing permissions and limitations under the Licence. + */ + +package eu.europa.ec.dashboardfeature.interactor + +import android.net.Uri + +sealed interface DocumentSignInteractorPartialState { + data class LaunchRQES(val uri: Uri) : DocumentSignInteractorPartialState +} + +interface DocumentSignInteractor { + fun launchRQESSdk(uri: Uri): DocumentSignInteractorPartialState +} + +class DocumentSignInteractorImpl : DocumentSignInteractor { + + override fun launchRQESSdk(uri: Uri): DocumentSignInteractorPartialState { + return DocumentSignInteractorPartialState.LaunchRQES(uri) + } +} \ No newline at end of file diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/router/Graph.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/router/Graph.kt index 11ff3551..da904107 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/router/Graph.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/router/Graph.kt @@ -23,6 +23,7 @@ import androidx.navigation.compose.navigation import androidx.navigation.navDeepLink import eu.europa.ec.dashboardfeature.BuildConfig import eu.europa.ec.dashboardfeature.ui.dashboard.DashboardScreen +import eu.europa.ec.dashboardfeature.ui.sign.DocumentSignScreen import eu.europa.ec.uilogic.navigation.DashboardScreens import eu.europa.ec.uilogic.navigation.ModuleRoute import org.koin.androidx.compose.koinViewModel @@ -43,5 +44,11 @@ fun NavGraphBuilder.featureDashboardGraph(navController: NavController) { ) { DashboardScreen(navController, koinViewModel()) } + + composable( + route = DashboardScreens.SignDocument.screenRoute + ) { + DocumentSignScreen(navController, koinViewModel()) + } } } \ No newline at end of file diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt index 5487db98..21ba0133 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt @@ -107,6 +107,7 @@ sealed class Event : ViewEvent { sealed class Options : BottomSheet() { data object OpenChangeQuickPin : Options() + data object OpenSignDocument : Options() data object OpenScanQr : Options() data object RetrieveLogs : Options() } @@ -219,6 +220,11 @@ class DashboardViewModel( icon = AppIcons.Edit, event = Event.BottomSheet.Options.OpenChangeQuickPin ), + ModalOptionUi( + title = resourceProvider.getString(R.string.dashboard_bottom_sheet_options_action_4), + icon = AppIcons.Sign, + event = Event.BottomSheet.Options.OpenSignDocument + ), ModalOptionUi( title = resourceProvider.getString(R.string.dashboard_bottom_sheet_options_action_2), icon = AppIcons.QrScanner, @@ -270,6 +276,12 @@ class DashboardViewModel( navigateToChangeQuickPin() } + is Event.BottomSheet.Options.OpenSignDocument -> { + hideBottomSheet() + navigateToDocumentSign() + + } + is Event.BottomSheet.Options.OpenScanQr -> { hideBottomSheet() navigateToQrScan() @@ -648,6 +660,14 @@ class DashboardViewModel( } } + private fun navigateToDocumentSign() { + setEffect { + Effect.Navigation.SwitchScreen( + screenRoute = DashboardScreens.SignDocument.screenRoute + ) + } + } + private fun startProximityFlow() { setState { copy(bleAvailability = BleAvailability.AVAILABLE) } // Create Koin scope for presentation diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt new file mode 100644 index 00000000..e2863f90 --- /dev/null +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023 European Commission + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work + * except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific language + * governing permissions and limitations under the Licence. + */ + +package eu.europa.ec.dashboardfeature.ui.sign + +import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import eu.europa.ec.resourceslogic.R +import eu.europa.ec.resourceslogic.theme.values.backgroundDefault +import eu.europa.ec.resourceslogic.theme.values.textPrimaryDark +import eu.europa.ec.uilogic.component.AppIcons +import eu.europa.ec.uilogic.component.content.ContentScreen +import eu.europa.ec.uilogic.component.content.ContentTitle +import eu.europa.ec.uilogic.component.content.ScreenNavigateAction +import eu.europa.ec.uilogic.component.utils.ALPHA_ENABLED +import eu.europa.ec.uilogic.component.utils.SPACING_MEDIUM +import eu.europa.ec.uilogic.component.utils.VSpacer +import eu.europa.ec.uilogic.component.wrap.WrapCard +import eu.europa.ec.uilogic.component.wrap.WrapIcon +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach + +@Composable +fun DocumentSignScreen( + navController: NavController, + viewModel: DocumentSignViewModel, +) { + val state = viewModel.viewState.value + + ContentScreen( + isLoading = state.isLoading, + navigatableAction = ScreenNavigateAction.BACKABLE, + onBack = { viewModel.setEvent(Event.Pop) }, + contentErrorConfig = state.error + ) { contentPadding -> + Content( + state = state, + effectFlow = viewModel.effect, + onEventSend = { viewModel.setEvent(it) }, + onNavigationRequested = { navigationEffect -> + when (navigationEffect) { + Effect.Navigation.Pop -> navController.popBackStack() + } + }, + paddingValues = contentPadding + ) + } +} + + +@Composable +fun Content( + state: State, + effectFlow: Flow, + onEventSend: (Event) -> Unit, + onNavigationRequested: (Effect.Navigation) -> Unit, + paddingValues: PaddingValues, +) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + ) { + ContentTitle( + title = state.title, + subtitle = state.subtitle, + ) + + VSpacer.Medium() + + SignButton(onEventSend) + } + + val selectPdfLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> + uri?.let { + onEventSend(Event.DocumentUriRetrieved(it)) + } + } + + val context = LocalContext.current + + LaunchedEffect(Unit) { + effectFlow.onEach { effect -> + when (effect) { + is Effect.Navigation.Pop -> onNavigationRequested(effect) + is Effect.OpenDocumentSelection -> selectPdfLauncher.launch(effect.selection) + is Effect.LaunchedRQES -> { + Toast.makeText( + context, + "Launched with: ${effect.uri}", + Toast.LENGTH_LONG + ).show() + } + } + }.collect() + } +} + +@Composable +fun SignButton(onEventSend: (Event) -> Unit) { + WrapCard( + onClick = { + onEventSend( + Event.OnSelectDocument + ) + }, + throttleClicks = true, + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.backgroundDefault, + ) + ) { + Row( + modifier = Modifier.padding(SPACING_MEDIUM.dp), + verticalAlignment = Alignment.CenterVertically + ) { + + val iconsColor = MaterialTheme.colorScheme.primary + val iconsAlpha = ALPHA_ENABLED + val textColor = MaterialTheme.colorScheme.textPrimaryDark + + Text( + modifier = Modifier.weight(1f), + text = stringResource(R.string.document_sign_select_document), + style = MaterialTheme.typography.titleMedium, + color = textColor + ) + + WrapIcon( + iconData = AppIcons.Add, + customTint = iconsColor, + contentAlpha = iconsAlpha + ) + } + } +} diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt new file mode 100644 index 00000000..93448980 --- /dev/null +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 European Commission + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work + * except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific language + * governing permissions and limitations under the Licence. + */ + +package eu.europa.ec.dashboardfeature.ui.sign + +import android.net.Uri +import eu.europa.ec.dashboardfeature.interactor.DocumentSignInteractor +import eu.europa.ec.dashboardfeature.interactor.DocumentSignInteractorPartialState +import eu.europa.ec.resourceslogic.provider.ResourceProvider +import eu.europa.ec.uilogic.component.content.ContentErrorConfig +import eu.europa.ec.uilogic.mvi.MviViewModel +import eu.europa.ec.uilogic.mvi.ViewEvent +import eu.europa.ec.uilogic.mvi.ViewSideEffect +import eu.europa.ec.uilogic.mvi.ViewState +import org.koin.android.annotation.KoinViewModel + +data class State( + val isLoading: Boolean = false, + val error: ContentErrorConfig? = null, + val title: String, + val subtitle: String, +) : ViewState + +sealed class Event : ViewEvent { + data object Pop : Event() + data object OnSelectDocument : Event() + data class DocumentUriRetrieved(val uri: Uri) : Event() +} + +sealed class Effect : ViewSideEffect { + sealed class Navigation : Effect() { + data object Pop : Navigation() + } + + data class OpenDocumentSelection(val selection: Array) : Effect() + data class LaunchedRQES(val uri: Uri) : Effect() +} + +@KoinViewModel +class DocumentSignViewModel( + private val documentSignInteractor: DocumentSignInteractor, + private val resourceProvider: ResourceProvider, +) : MviViewModel() { + + override fun setInitialState(): State = State( + title = resourceProvider.getString(eu.europa.ec.resourceslogic.R.string.document_sign_title), + subtitle = resourceProvider.getString(eu.europa.ec.resourceslogic.R.string.document_sign_subtitle) + ) + + override fun handleEvents(event: Event) { + when (event) { + is Event.OnSelectDocument -> { + setEffect { Effect.OpenDocumentSelection(arrayOf("application/pdf")) } + } + + is Event.Pop -> setEffect { Effect.Navigation.Pop } + is Event.DocumentUriRetrieved -> { + when (documentSignInteractor.launchRQESSdk(event.uri)) { + is DocumentSignInteractorPartialState.LaunchRQES -> setEffect { + Effect.LaunchedRQES( + event.uri + ) + } + } + } + } + } +} \ No newline at end of file diff --git a/resources-logic/src/main/res/drawable/ic_sign_document.xml b/resources-logic/src/main/res/drawable/ic_sign_document.xml new file mode 100644 index 00000000..96c87573 --- /dev/null +++ b/resources-logic/src/main/res/drawable/ic_sign_document.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/resources-logic/src/main/res/values/strings.xml b/resources-logic/src/main/res/values/strings.xml index 057d1db9..df898d8c 100644 --- a/resources-logic/src/main/res/values/strings.xml +++ b/resources-logic/src/main/res/values/strings.xml @@ -164,6 +164,7 @@ Change quick pin Scan a QR code Retrieve logs + Sign document Enable bluetooth? Enable bluetooth to share your information using the QR/TAP option @@ -179,6 +180,11 @@ New documents have been added to your wallet. Share logs + + Sign Document + Select a document from your device to sign electronically. + Select document + Camera permission not provided\nOpen App Settings Having trouble scanning the QR Code?\nPlease try an alternative way diff --git a/ui-logic/src/main/java/eu/europa/ec/uilogic/component/AppIcons.kt b/ui-logic/src/main/java/eu/europa/ec/uilogic/component/AppIcons.kt index e2b52970..afc3baac 100644 --- a/ui-logic/src/main/java/eu/europa/ec/uilogic/component/AppIcons.kt +++ b/ui-logic/src/main/java/eu/europa/ec/uilogic/component/AppIcons.kt @@ -178,6 +178,12 @@ object AppIcons { imageVector = null ) + val Sign: IconData = IconData( + resourceId = R.drawable.ic_sign_document, + contentDescriptionId = R.string.content_description_edit_icon, + imageVector = null + ) + val QrScanner: IconData = IconData( resourceId = R.drawable.ic_qr_scanner, contentDescriptionId = R.string.content_description_qr_scanner_icon, diff --git a/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/RouterContract.kt b/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/RouterContract.kt index a46f5676..e7d707bd 100644 --- a/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/RouterContract.kt +++ b/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/RouterContract.kt @@ -45,6 +45,8 @@ sealed class CommonScreens { sealed class DashboardScreens { data object Dashboard : Screen(name = "DASHBOARD") + data object SignDocument : + Screen(name = "SIGN_DOCUMENT") } sealed class LoginScreens { From 901e0a1232dc9bcd218ef201fe33fa84b376c003 Mon Sep 17 00:00:00 2001 From: STYLIATIS Stamatis Date: Fri, 15 Nov 2024 13:09:38 +0200 Subject: [PATCH 02/10] Fixed function accesibility --- .../ec/dashboardfeature/ui/sign/DocumentSignScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt index e2863f90..3ac3e2c0 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt @@ -52,7 +52,7 @@ import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach @Composable -fun DocumentSignScreen( +internal fun DocumentSignScreen( navController: NavController, viewModel: DocumentSignViewModel, ) { @@ -80,7 +80,7 @@ fun DocumentSignScreen( @Composable -fun Content( +private fun Content( state: State, effectFlow: Flow, onEventSend: (Event) -> Unit, @@ -130,7 +130,7 @@ fun Content( } @Composable -fun SignButton(onEventSend: (Event) -> Unit) { +private fun SignButton(onEventSend: (Event) -> Unit) { WrapCard( onClick = { onEventSend( From 1b087107667843fcf84aad059a7dba9229232c0f Mon Sep 17 00:00:00 2001 From: Stilianos Tzouvaras Date: Tue, 19 Nov 2024 00:36:23 +0200 Subject: [PATCH 03/10] RQES SDK Integration, first draft --- assembly-logic/build.gradle.kts | 1 + assembly-logic/src/main/AndroidManifest.xml | 12 +++++++ .../eu/europa/ec/assemblylogic/Application.kt | 18 +++++++++- .../ec/assemblylogic/di/AssemblyModule.kt | 5 +-- build-logic/convention/build.gradle.kts | 4 +++ .../kotlin/AndroidLibraryConventionPlugin.kt | 11 +++++++ .../src/main/kotlin/EudiRqesPlugin.kt | 30 +++++++++++++++++ .../project/convention/logic/KotlinAndroid.kt | 2 +- build-logic/settings.gradle.kts | 1 + business-logic/build.gradle.kts | 1 + .../businesslogic/config/ConfigLogicImpl.kt | 33 +++++++++++++++++++ .../businesslogic/config/ConfigLogicImpl.kt | 32 ++++++++++++++++++ .../ec/businesslogic/config/ConfigLogic.kt | 6 ++++ dashboard-feature/build.gradle.kts | 1 + .../interactor/DocumentSignInteractor.kt | 13 +++----- .../ui/sign/DocumentSignScreen.kt | 9 ++--- .../ui/sign/DocumentSignViewModel.kt | 17 ++++------ gradle/libs.versions.toml | 2 ++ settings.gradle.kts | 1 + ui-logic/build.gradle.kts | 1 + .../container/EudiComponentActivity.kt | 2 +- .../navigation/helper/DeepLinkHelper.kt | 20 ++++++++++- 22 files changed, 193 insertions(+), 29 deletions(-) create mode 100644 build-logic/convention/src/main/kotlin/EudiRqesPlugin.kt diff --git a/assembly-logic/build.gradle.kts b/assembly-logic/build.gradle.kts index 22e62d09..8ac366d4 100644 --- a/assembly-logic/build.gradle.kts +++ b/assembly-logic/build.gradle.kts @@ -36,6 +36,7 @@ import project.convention.logic.kover.koverModules plugins { id("project.android.library") id("project.android.library.compose") + id("project.rqes.sdk") } android { diff --git a/assembly-logic/src/main/AndroidManifest.xml b/assembly-logic/src/main/AndroidManifest.xml index 61b72626..c4f8d240 100644 --- a/assembly-logic/src/main/AndroidManifest.xml +++ b/assembly-logic/src/main/AndroidManifest.xml @@ -166,6 +166,18 @@ android:scheme="${openId4VciAuthorizationScheme}" /> + + + + + + + + + diff --git a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt index 9422434a..a6b81fe0 100644 --- a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt +++ b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt @@ -19,22 +19,38 @@ package eu.europa.ec.assemblylogic import android.app.Application import eu.europa.ec.analyticslogic.controller.AnalyticsController import eu.europa.ec.assemblylogic.di.setupKoin +import eu.europa.ec.businesslogic.config.ConfigLogic import eu.europa.ec.corelogic.config.WalletCoreConfig +import eu.europa.ec.eudi.rqesui.infrastructure.EudiRQESUi import eu.europa.ec.eudi.wallet.EudiWallet import org.koin.android.ext.android.inject +import org.koin.core.KoinApplication class Application : Application() { private val configWalletCore: WalletCoreConfig by inject() private val analyticsController: AnalyticsController by inject() + private val configLogic: ConfigLogic by inject() override fun onCreate() { super.onCreate() - setupKoin() + initializeKoin().initializeRqes() initializeReporting() initializeEudiWallet() } + private fun KoinApplication.initializeRqes() { + EudiRQESUi.setup( + application = this@Application, + config = configLogic.rqesConfig, + koinApplication = this@initializeRqes + ) + } + + private fun initializeKoin(): KoinApplication { + return setupKoin() + } + private fun initializeReporting() { analyticsController.initialize(this) } diff --git a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/di/AssemblyModule.kt b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/di/AssemblyModule.kt index e1289259..108a9c7e 100644 --- a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/di/AssemblyModule.kt +++ b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/di/AssemblyModule.kt @@ -33,6 +33,7 @@ import eu.europa.ec.startupfeature.di.FeatureStartupModule import eu.europa.ec.uilogic.di.LogicUiModule import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidLogger +import org.koin.core.KoinApplication import org.koin.core.context.GlobalContext.startKoin import org.koin.ksp.generated.module @@ -57,8 +58,8 @@ private val assembledModules = listOf( FeatureIssuanceModule().module ) -internal fun Application.setupKoin() { - startKoin { +internal fun Application.setupKoin(): KoinApplication { + return startKoin { androidContext(this@setupKoin) androidLogger() modules(assembledModules) diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 1da129b7..0f29df25 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -112,5 +112,9 @@ gradlePlugin { id = "project.android.base.profile" implementationClass = "AndroidBaseLineProfilePlugin" } + register("eudiRqes") { + id = "project.rqes.sdk" + implementationClass = "EudiRqesPlugin" + } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index a1ba855b..9226aa39 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -58,6 +58,10 @@ class AndroidLibraryConventionPlugin : Plugin { val openId4VciAuthorizationScheme = "eu.europa.ec.euidi" val openId4VciAuthorizationHost = "authorization" + val rqesScheme = "rqes" + val rqesHost = "oauth" + val rqesPath = "/callback" + with(pluginManager) { apply("com.android.library") apply("project.android.library.kover") @@ -87,6 +91,8 @@ class AndroidLibraryConventionPlugin : Plugin { "ISSUE_AUTHORIZATION_DEEPLINK", "$openId4VciAuthorizationScheme://$openId4VciAuthorizationHost" ) + addConfigField("RQES_SCHEME", rqesScheme) + addConfigField("RQES_DEEPLINK", "$rqesScheme://$rqesHost$rqesPath") // Manifest placeholders for Wallet deepLink manifestPlaceholders["deepLinkScheme"] = walletScheme @@ -109,6 +115,11 @@ class AndroidLibraryConventionPlugin : Plugin { openId4VciAuthorizationScheme manifestPlaceholders["openId4VciAuthorizationHost"] = openId4VciAuthorizationHost + + // Manifest placeholders used for RQES + manifestPlaceholders["rqesHost"] = rqesHost + manifestPlaceholders["rqesScheme"] = rqesScheme + manifestPlaceholders["rqesPath"] = rqesPath } configureFlavors(this) configureGradleManagedDevices(this) diff --git a/build-logic/convention/src/main/kotlin/EudiRqesPlugin.kt b/build-logic/convention/src/main/kotlin/EudiRqesPlugin.kt new file mode 100644 index 00000000..f56f8bc9 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/EudiRqesPlugin.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 European Commission + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work + * except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific language + * governing permissions and limitations under the Licence. + */ + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies +import project.convention.logic.libs + +class EudiRqesPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + dependencies { + add("implementation", libs.findLibrary("rqes-ui-sdk").get()) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/project/convention/logic/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/project/convention/logic/KotlinAndroid.kt index 0e0aab66..11f0b5ac 100644 --- a/build-logic/convention/src/main/kotlin/project/convention/logic/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/project/convention/logic/KotlinAndroid.kt @@ -37,7 +37,7 @@ internal fun Project.configureKotlinAndroid( compileSdk = 35 defaultConfig { - minSdk = 26 + minSdk = 28 } buildFeatures { diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts index 049cf87a..f1357575 100644 --- a/build-logic/settings.gradle.kts +++ b/build-logic/settings.gradle.kts @@ -18,6 +18,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + mavenLocal() maven { url = uri("https://plugins.gradle.org/m2/") } diff --git a/business-logic/build.gradle.kts b/business-logic/build.gradle.kts index c6755284..f6c4f42f 100644 --- a/business-logic/build.gradle.kts +++ b/business-logic/build.gradle.kts @@ -20,6 +20,7 @@ import project.convention.logic.kover.excludeFromKoverReport plugins { id("project.android.library") + id("project.rqes.sdk") } android { diff --git a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt index c315cda1..8f7960e2 100644 --- a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt +++ b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt @@ -16,12 +16,24 @@ package eu.europa.ec.businesslogic.config +import eu.europa.ec.businesslogic.BuildConfig +import eu.europa.ec.eudi.rqes.HashAlgorithmOID +import eu.europa.ec.eudi.rqes.SigningAlgorithmOID +import eu.europa.ec.eudi.rqesui.domain.extension.toUri +import eu.europa.ec.eudi.rqesui.infrastructure.config.EudiRQESUiConfig +import eu.europa.ec.eudi.rqesui.infrastructure.config.RqesServiceConfig +import eu.europa.ec.eudi.rqesui.infrastructure.config.data.QtspData +import java.net.URI + class ConfigLogicImpl : ConfigLogic { override val appFlavor: AppFlavor get() = AppFlavor.DEMO override val environmentConfig: EnvironmentConfig get() = DemoEnvironmentConfig() + + override val rqesConfig: EudiRQESUiConfig + get() = RqesConfig() } private class DemoEnvironmentConfig : EnvironmentConfig() { @@ -29,4 +41,25 @@ private class DemoEnvironmentConfig : EnvironmentConfig() { ServerConfig.Debug -> "" ServerConfig.Release -> "" } +} + +private class RqesConfig : EudiRQESUiConfig { + + override val rqesServiceConfig: RqesServiceConfig + get() = RqesServiceConfig( + clientId = "wallet-client-tester", + clientSecret = "somesecrettester2", + authFlowRedirectionURI = URI.create(BuildConfig.RQES_DEEPLINK), + signingAlgorithm = SigningAlgorithmOID.RSA, + hashAlgorithm = HashAlgorithmOID.SHA_256, + ) + + override val qtsps: List + get() = listOf( + QtspData( + name = "Wallet-Centric", + endpoint = "https://walletcentric.signer.eudiw.dev/csc/v2".toUri(), + scaUrl = "https://walletcentric.signer.eudiw.dev", + ) + ) } \ No newline at end of file diff --git a/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt b/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt index 7a76f345..373b5b7c 100644 --- a/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt +++ b/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt @@ -16,12 +16,23 @@ package eu.europa.ec.businesslogic.config +import eu.europa.ec.eudi.rqes.HashAlgorithmOID +import eu.europa.ec.eudi.rqes.SigningAlgorithmOID +import eu.europa.ec.eudi.rqesui.domain.extension.toUri +import eu.europa.ec.eudi.rqesui.infrastructure.config.EudiRQESUiConfig +import eu.europa.ec.eudi.rqesui.infrastructure.config.RqesServiceConfig +import eu.europa.ec.eudi.rqesui.infrastructure.config.data.QtspData +import java.net.URI + class ConfigLogicImpl : ConfigLogic { override val appFlavor: AppFlavor get() = AppFlavor.DEV override val environmentConfig: EnvironmentConfig get() = DevEnvironmentConfig() + + override val rqesConfig: EudiRQESUiConfig + get() = RqesConfig() } private class DevEnvironmentConfig : EnvironmentConfig() { @@ -29,4 +40,25 @@ private class DevEnvironmentConfig : EnvironmentConfig() { ServerConfig.Debug -> "" ServerConfig.Release -> "" } +} + +private class RqesConfig : EudiRQESUiConfig { + + override val rqesServiceConfig: RqesServiceConfig + get() = RqesServiceConfig( + clientId = "wallet-client-tester", + clientSecret = "somesecrettester2", + authFlowRedirectionURI = URI.create("rQES://oauth/callback"), + signingAlgorithm = SigningAlgorithmOID.RSA, + hashAlgorithm = HashAlgorithmOID.SHA_256, + ) + + override val qtsps: List + get() = listOf( + QtspData( + name = "Wallet-Centric", + endpoint = "https://walletcentric.signer.eudiw.dev/csc/v2".toUri(), + scaUrl = "https://walletcentric.signer.eudiw.dev", + ) + ) } \ No newline at end of file diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigLogic.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigLogic.kt index 79ccc041..42eddfb9 100644 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigLogic.kt +++ b/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigLogic.kt @@ -17,6 +17,7 @@ package eu.europa.ec.businesslogic.config import eu.europa.ec.businesslogic.BuildConfig +import eu.europa.ec.eudi.rqesui.infrastructure.config.EudiRQESUiConfig interface ConfigLogic { @@ -39,6 +40,11 @@ interface ConfigLogic { * Application version. */ val appVersion: String get() = BuildConfig.APP_VERSION + + /** + * RQES Config. + */ + val rqesConfig: EudiRQESUiConfig } enum class AppFlavor { diff --git a/dashboard-feature/build.gradle.kts b/dashboard-feature/build.gradle.kts index 7f603193..e09f32f4 100644 --- a/dashboard-feature/build.gradle.kts +++ b/dashboard-feature/build.gradle.kts @@ -20,6 +20,7 @@ import project.convention.logic.kover.excludeFromKoverReport plugins { id("project.android.feature") + id("project.rqes.sdk") } android { diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt index 861643cb..50feb729 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/interactor/DocumentSignInteractor.kt @@ -16,19 +16,16 @@ package eu.europa.ec.dashboardfeature.interactor +import android.content.Context import android.net.Uri - -sealed interface DocumentSignInteractorPartialState { - data class LaunchRQES(val uri: Uri) : DocumentSignInteractorPartialState -} +import eu.europa.ec.eudi.rqesui.infrastructure.EudiRQESUi interface DocumentSignInteractor { - fun launchRQESSdk(uri: Uri): DocumentSignInteractorPartialState + fun launchRQESSdk(context: Context, uri: Uri) } class DocumentSignInteractorImpl : DocumentSignInteractor { - - override fun launchRQESSdk(uri: Uri): DocumentSignInteractorPartialState { - return DocumentSignInteractorPartialState.LaunchRQES(uri) + override fun launchRQESSdk(context: Context, uri: Uri) { + EudiRQESUi.initiate(context, uri) } } \ No newline at end of file diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt index 3ac3e2c0..a7634e9f 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignScreen.kt @@ -60,7 +60,7 @@ internal fun DocumentSignScreen( ContentScreen( isLoading = state.isLoading, - navigatableAction = ScreenNavigateAction.BACKABLE, + navigatableAction = ScreenNavigateAction.CANCELABLE, onBack = { viewModel.setEvent(Event.Pop) }, contentErrorConfig = state.error ) { contentPadding -> @@ -87,6 +87,9 @@ private fun Content( onNavigationRequested: (Effect.Navigation) -> Unit, paddingValues: PaddingValues, ) { + + val context = LocalContext.current + Column( modifier = Modifier .fillMaxSize() @@ -106,12 +109,10 @@ private fun Content( contract = ActivityResultContracts.OpenDocument(), ) { uri -> uri?.let { - onEventSend(Event.DocumentUriRetrieved(it)) + onEventSend(Event.DocumentUriRetrieved(context, it)) } } - val context = LocalContext.current - LaunchedEffect(Unit) { effectFlow.onEach { effect -> when (effect) { diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt index 93448980..74d11df4 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/sign/DocumentSignViewModel.kt @@ -16,9 +16,9 @@ package eu.europa.ec.dashboardfeature.ui.sign +import android.content.Context import android.net.Uri import eu.europa.ec.dashboardfeature.interactor.DocumentSignInteractor -import eu.europa.ec.dashboardfeature.interactor.DocumentSignInteractorPartialState import eu.europa.ec.resourceslogic.provider.ResourceProvider import eu.europa.ec.uilogic.component.content.ContentErrorConfig import eu.europa.ec.uilogic.mvi.MviViewModel @@ -37,7 +37,7 @@ data class State( sealed class Event : ViewEvent { data object Pop : Event() data object OnSelectDocument : Event() - data class DocumentUriRetrieved(val uri: Uri) : Event() + data class DocumentUriRetrieved(val context: Context, val uri: Uri) : Event() } sealed class Effect : ViewSideEffect { @@ -67,15 +67,10 @@ class DocumentSignViewModel( } is Event.Pop -> setEffect { Effect.Navigation.Pop } - is Event.DocumentUriRetrieved -> { - when (documentSignInteractor.launchRQESSdk(event.uri)) { - is DocumentSignInteractorPartialState.LaunchRQES -> setEffect { - Effect.LaunchedRQES( - event.uri - ) - } - } - } + is Event.DocumentUriRetrieved -> documentSignInteractor.launchRQESSdk( + event.context, + event.uri + ) } } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 235e7ba8..3eb5b70f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -67,6 +67,7 @@ sonar = "5.0.0.4638" baselineprofile = "1.3.3" timber = "5.0.1" treessence = "1.1.2" +rqesUiSDK = "0.0.1-SNAPSHOT" [libraries] accompanist-permissions = { group = "com.google.accompanist", name = "accompanist-permissions", version.ref = "accompanist" } @@ -154,6 +155,7 @@ appcenter-crashes = { group = "com.microsoft.appcenter", name = "appcenter-crash appcenter-distribute = { group = "com.microsoft.appcenter", name = "appcenter-distribute", version.ref = "appCenter" } timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" } treessence = { group = "com.github.bastienpaulfr", name = "Treessence", version.ref = "treessence" } +rqes-ui-sdk = { group = "eu.europa.ec.eudi", name = "eudi-lib-android-rqes-ui", version.ref = "rqesUiSDK" } # Dependencies of the included build-logic android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index f71149a1..c64e80d2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,6 +27,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + mavenLocal() maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") mavenContent { snapshotsOnly() } diff --git a/ui-logic/build.gradle.kts b/ui-logic/build.gradle.kts index ee5a8919..2328d558 100644 --- a/ui-logic/build.gradle.kts +++ b/ui-logic/build.gradle.kts @@ -21,6 +21,7 @@ import project.convention.logic.kover.excludeFromKoverReport plugins { id("project.android.library") id("project.android.library.compose") + id("project.rqes.sdk") } android { diff --git a/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt b/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt index 9cef3087..56f3b451 100644 --- a/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt +++ b/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt @@ -74,7 +74,7 @@ open class EudiComponentActivity : FragmentActivity() { } } - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) if (flowStarted) { handleDeepLink(intent) diff --git a/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt b/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt index b44430c5..591b394e 100644 --- a/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt +++ b/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt @@ -25,6 +25,7 @@ import androidx.core.os.bundleOf import androidx.navigation.NavController import eu.europa.ec.businesslogic.util.safeLet import eu.europa.ec.corelogic.util.CoreActions +import eu.europa.ec.eudi.rqesui.infrastructure.EudiRQESUi import eu.europa.ec.uilogic.BuildConfig import eu.europa.ec.uilogic.container.EudiComponentActivity import eu.europa.ec.uilogic.extension.openUrl @@ -137,6 +138,16 @@ fun handleDeepLinkAction( ) return } + + DeepLinkType.RQES -> { + action.link.getQueryParameter("code")?.let { + EudiRQESUi.resume( + context = navController.context, + authorizationCode = it + ) + } + return + } } val navigationLink = arguments?.let { @@ -173,6 +184,9 @@ enum class DeepLinkType(val schemas: List, val host: String? = null) { ), DYNAMIC_PRESENTATION( emptyList() + ), + RQES( + schemas = listOf(BuildConfig.RQES_SCHEME) ); companion object { @@ -190,6 +204,10 @@ enum class DeepLinkType(val schemas: List, val host: String? = null) { ISSUANCE } + RQES.schemas.contains(scheme) -> { + RQES + } + else -> EXTERNAL } } @@ -197,7 +215,7 @@ enum class DeepLinkType(val schemas: List, val host: String? = null) { private fun notify(context: Context, action: String, bundle: Bundle? = null) { Intent().also { intent -> - intent.setAction(action) + intent.action = action bundle?.let { intent.putExtras(it) } context.sendBroadcast(intent) } From a6a1407294215cb4fb7195500e8be72a495faf79 Mon Sep 17 00:00:00 2001 From: Stilianos Tzouvaras Date: Tue, 19 Nov 2024 00:59:47 +0200 Subject: [PATCH 04/10] temporary fix for deeplink RQES --- .../java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt index 8f7960e2..af5eb6b8 100644 --- a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt +++ b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt @@ -16,7 +16,6 @@ package eu.europa.ec.businesslogic.config -import eu.europa.ec.businesslogic.BuildConfig import eu.europa.ec.eudi.rqes.HashAlgorithmOID import eu.europa.ec.eudi.rqes.SigningAlgorithmOID import eu.europa.ec.eudi.rqesui.domain.extension.toUri @@ -49,7 +48,7 @@ private class RqesConfig : EudiRQESUiConfig { get() = RqesServiceConfig( clientId = "wallet-client-tester", clientSecret = "somesecrettester2", - authFlowRedirectionURI = URI.create(BuildConfig.RQES_DEEPLINK), + authFlowRedirectionURI = URI.create("rQES://oauth/callback"), signingAlgorithm = SigningAlgorithmOID.RSA, hashAlgorithm = HashAlgorithmOID.SHA_256, ) From 62dfff3bf272c8f99524a98301e6a08eebe22901 Mon Sep 17 00:00:00 2001 From: Stilianos Tzouvaras Date: Tue, 19 Nov 2024 01:18:18 +0200 Subject: [PATCH 05/10] RQES SDK uploaded to sonatype, mavenLocal is no longer needed --- build-logic/settings.gradle.kts | 1 - settings.gradle.kts | 1 - 2 files changed, 2 deletions(-) diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts index f1357575..049cf87a 100644 --- a/build-logic/settings.gradle.kts +++ b/build-logic/settings.gradle.kts @@ -18,7 +18,6 @@ dependencyResolutionManagement { repositories { google() mavenCentral() - mavenLocal() maven { url = uri("https://plugins.gradle.org/m2/") } diff --git a/settings.gradle.kts b/settings.gradle.kts index c64e80d2..f71149a1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,7 +27,6 @@ dependencyResolutionManagement { repositories { google() mavenCentral() - mavenLocal() maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") mavenContent { snapshotsOnly() } From 78d8e9931497c2ad44de87e20adf212202443194 Mon Sep 17 00:00:00 2001 From: Stilianos Tzouvaras Date: Tue, 19 Nov 2024 10:56:44 +0200 Subject: [PATCH 06/10] new client id and secret for RQES Config --- .../java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt | 4 ++-- .../java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt index af5eb6b8..f64b9d1f 100644 --- a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt +++ b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt @@ -46,8 +46,8 @@ private class RqesConfig : EudiRQESUiConfig { override val rqesServiceConfig: RqesServiceConfig get() = RqesServiceConfig( - clientId = "wallet-client-tester", - clientSecret = "somesecrettester2", + clientId = "wallet-client", + clientSecret = "somesecret2", authFlowRedirectionURI = URI.create("rQES://oauth/callback"), signingAlgorithm = SigningAlgorithmOID.RSA, hashAlgorithm = HashAlgorithmOID.SHA_256, diff --git a/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt b/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt index 373b5b7c..6514fd1a 100644 --- a/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt +++ b/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt @@ -46,8 +46,8 @@ private class RqesConfig : EudiRQESUiConfig { override val rqesServiceConfig: RqesServiceConfig get() = RqesServiceConfig( - clientId = "wallet-client-tester", - clientSecret = "somesecrettester2", + clientId = "wallet-client", + clientSecret = "somesecret2", authFlowRedirectionURI = URI.create("rQES://oauth/callback"), signingAlgorithm = SigningAlgorithmOID.RSA, hashAlgorithm = HashAlgorithmOID.SHA_256, From 7ee68c2733b657da2caa4a1ac7392be48bf0fbf8 Mon Sep 17 00:00:00 2001 From: Stilianos Tzouvaras Date: Tue, 19 Nov 2024 11:48:41 +0200 Subject: [PATCH 07/10] for RQES deeplink check the host as well. --- .../src/main/kotlin/AndroidLibraryConventionPlugin.kt | 1 + .../eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index 9226aa39..924da9fb 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -92,6 +92,7 @@ class AndroidLibraryConventionPlugin : Plugin { "$openId4VciAuthorizationScheme://$openId4VciAuthorizationHost" ) addConfigField("RQES_SCHEME", rqesScheme) + addConfigField("RQES_HOST", rqesHost) addConfigField("RQES_DEEPLINK", "$rqesScheme://$rqesHost$rqesPath") // Manifest placeholders for Wallet deepLink diff --git a/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt b/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt index 591b394e..97d7f7c4 100644 --- a/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt +++ b/ui-logic/src/main/java/eu/europa/ec/uilogic/navigation/helper/DeepLinkHelper.kt @@ -186,7 +186,8 @@ enum class DeepLinkType(val schemas: List, val host: String? = null) { emptyList() ), RQES( - schemas = listOf(BuildConfig.RQES_SCHEME) + schemas = listOf(BuildConfig.RQES_SCHEME), + host = BuildConfig.RQES_HOST ); companion object { @@ -204,7 +205,7 @@ enum class DeepLinkType(val schemas: List, val host: String? = null) { ISSUANCE } - RQES.schemas.contains(scheme) -> { + RQES.schemas.contains(scheme) && host == RQES.host -> { RQES } From 2ead18681ffbcc76aef477747370ee3247654199 Mon Sep 17 00:00:00 2001 From: Stilianos Tzouvaras Date: Tue, 19 Nov 2024 12:34:37 +0200 Subject: [PATCH 08/10] RQES config dynamic authFlowRedirectionURI from BuildConfig --- .../java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt | 3 ++- .../java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt index f64b9d1f..ba978601 100644 --- a/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt +++ b/business-logic/src/demo/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt @@ -16,6 +16,7 @@ package eu.europa.ec.businesslogic.config +import eu.europa.ec.businesslogic.BuildConfig import eu.europa.ec.eudi.rqes.HashAlgorithmOID import eu.europa.ec.eudi.rqes.SigningAlgorithmOID import eu.europa.ec.eudi.rqesui.domain.extension.toUri @@ -48,7 +49,7 @@ private class RqesConfig : EudiRQESUiConfig { get() = RqesServiceConfig( clientId = "wallet-client", clientSecret = "somesecret2", - authFlowRedirectionURI = URI.create("rQES://oauth/callback"), + authFlowRedirectionURI = URI.create(BuildConfig.RQES_DEEPLINK), signingAlgorithm = SigningAlgorithmOID.RSA, hashAlgorithm = HashAlgorithmOID.SHA_256, ) diff --git a/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt b/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt index 6514fd1a..6dea9144 100644 --- a/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt +++ b/business-logic/src/dev/java/eu/europa/ec/businesslogic/config/ConfigLogicImpl.kt @@ -16,6 +16,7 @@ package eu.europa.ec.businesslogic.config +import eu.europa.ec.businesslogic.BuildConfig import eu.europa.ec.eudi.rqes.HashAlgorithmOID import eu.europa.ec.eudi.rqes.SigningAlgorithmOID import eu.europa.ec.eudi.rqesui.domain.extension.toUri @@ -48,7 +49,7 @@ private class RqesConfig : EudiRQESUiConfig { get() = RqesServiceConfig( clientId = "wallet-client", clientSecret = "somesecret2", - authFlowRedirectionURI = URI.create("rQES://oauth/callback"), + authFlowRedirectionURI = URI.create(BuildConfig.RQES_DEEPLINK), signingAlgorithm = SigningAlgorithmOID.RSA, hashAlgorithm = HashAlgorithmOID.SHA_256, ) From de170bb8be7b0413924fef210f0ea3769622155b Mon Sep 17 00:00:00 2001 From: Stilianos Tzouvaras Date: Tue, 19 Nov 2024 14:58:24 +0200 Subject: [PATCH 09/10] correction for Sign document modal option order --- .../ui/dashboard/DashboardViewModel.kt | 10 +++++----- gradle/libs.versions.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt index 21ba0133..e0367109 100644 --- a/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt +++ b/dashboard-feature/src/main/java/eu/europa/ec/dashboardfeature/ui/dashboard/DashboardViewModel.kt @@ -220,16 +220,16 @@ class DashboardViewModel( icon = AppIcons.Edit, event = Event.BottomSheet.Options.OpenChangeQuickPin ), - ModalOptionUi( - title = resourceProvider.getString(R.string.dashboard_bottom_sheet_options_action_4), - icon = AppIcons.Sign, - event = Event.BottomSheet.Options.OpenSignDocument - ), ModalOptionUi( title = resourceProvider.getString(R.string.dashboard_bottom_sheet_options_action_2), icon = AppIcons.QrScanner, event = Event.BottomSheet.Options.OpenScanQr ), + ModalOptionUi( + title = resourceProvider.getString(R.string.dashboard_bottom_sheet_options_action_4), + icon = AppIcons.Sign, + event = Event.BottomSheet.Options.OpenSignDocument + ), ModalOptionUi( title = resourceProvider.getString(R.string.dashboard_bottom_sheet_options_action_3), icon = AppIcons.OpenNew, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3eb5b70f..b90c973a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -67,7 +67,7 @@ sonar = "5.0.0.4638" baselineprofile = "1.3.3" timber = "5.0.1" treessence = "1.1.2" -rqesUiSDK = "0.0.1-SNAPSHOT" +rqesUiSDK = "0.0.2-SNAPSHOT" [libraries] accompanist-permissions = { group = "com.google.accompanist", name = "accompanist-permissions", version.ref = "accompanist" } From 4e6408184206a698418f8100b0f9cf41a115902f Mon Sep 17 00:00:00 2001 From: Stylianos Tzouvaras Date: Wed, 20 Nov 2024 13:22:00 +0200 Subject: [PATCH 10/10] new RQES Snapshot version --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b90c973a..cdf0d358 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -67,7 +67,7 @@ sonar = "5.0.0.4638" baselineprofile = "1.3.3" timber = "5.0.1" treessence = "1.1.2" -rqesUiSDK = "0.0.2-SNAPSHOT" +rqesUiSDK = "0.0.3-SNAPSHOT" [libraries] accompanist-permissions = { group = "com.google.accompanist", name = "accompanist-permissions", version.ref = "accompanist" }