Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ fun SignatureInputScreen(
SigningMethod.MOBILE_ID ->
MobileIdView(
modifier = modifier,
activity = context,
onError = {
isSigning = false
isAddingRoleAndAddress = false
Expand Down Expand Up @@ -272,7 +271,6 @@ fun SignatureInputScreen(
SigningMethod.SMART_ID ->
SmartIdView(
modifier = modifier,
activity = context,
onError = {
isSigning = false
isAddingRoleAndAddress = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@

package ee.ria.DigiDoc.ui.component.signing

import android.app.Activity
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalActivity
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
Expand All @@ -28,7 +25,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
Expand Down Expand Up @@ -82,7 +78,6 @@ import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
fun MobileIdView(
activity: Activity,
modifier: Modifier = Modifier,
isSigning: Boolean,
onError: () -> Unit = {},
Expand All @@ -99,27 +94,12 @@ fun MobileIdView(
val context = LocalContext.current
val signedContainer by sharedContainerViewModel.signedContainer.collectAsState()
val dialogError by mobileIdViewModel.dialogError.asFlow().collectAsState(0)
val isSigningInProgress by mobileIdViewModel.signingInProgress.collectAsState()
val getSettingsAskRoleAndAddress = sharedSettingsViewModel.dataStore::getSettingsAskRoleAndAddress

var shouldRememberMe by rememberSaveable { mutableStateOf(rememberMe) }

val focusManager = LocalFocusManager.current

DisposableEffect(isSigningInProgress) {
if (isSigningInProgress) {
activity.requestedOrientation =
if (activity.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
} else {
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
}
onDispose {
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
}

var countryCodeAndPhone by rememberSaveable(stateSaver = textFieldValueSaver) {
mutableStateOf(
TextFieldValue(
Expand Down Expand Up @@ -184,6 +164,12 @@ fun MobileIdView(
val phoneNumberFocusRequester = remember { FocusRequester() }
val personalCodeFocusRequester = remember { FocusRequester() }

LaunchedEffect(signedContainer) {
cancelAction {
mobileIdViewModel.cancelMobileIdWorkRequest(signedContainer)
}
}

BackHandler {
if (isSigning) {
onError()
Expand Down Expand Up @@ -384,9 +370,6 @@ fun MobileIdView(
roleData = roleDataRequest,
)
}
cancelAction {
mobileIdViewModel.cancelMobileIdWorkRequest(signedContainer)
}
}
}

Expand Down Expand Up @@ -478,7 +461,6 @@ fun MobileIdViewPreview() {
val sharedContainerViewModel: SharedContainerViewModel = hiltViewModel()
RIADigiDocTheme {
MobileIdView(
activity = LocalActivity.current as Activity,
sharedSettingsViewModel = sharedSettingsViewModel,
sharedContainerViewModel = sharedContainerViewModel,
isSigning = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@

package ee.ria.DigiDoc.ui.component.signing

import android.app.Activity
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalActivity
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
Expand All @@ -33,7 +30,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
Expand Down Expand Up @@ -95,7 +91,6 @@ import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
fun SmartIdView(
activity: Activity,
modifier: Modifier = Modifier,
isSigning: Boolean,
onError: () -> Unit = {},
Expand All @@ -112,25 +107,10 @@ fun SmartIdView(
val context = LocalContext.current
val signedContainer by sharedContainerViewModel.signedContainer.collectAsState()
val dialogError by smartIdViewModel.dialogError.asFlow().collectAsState(0)
val isSigningInProgress by smartIdViewModel.signingInProgress.collectAsState()
val getSettingsAskRoleAndAddress = sharedSettingsViewModel.dataStore::getSettingsAskRoleAndAddress

val focusManager = LocalFocusManager.current

DisposableEffect(isSigningInProgress) {
if (isSigningInProgress) {
activity.requestedOrientation =
if (activity.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
} else {
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
}
onDispose {
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
}

val countryOptions = stringArrayResource(id = R.array.smart_id_country)
var selectedCountry by rememberSaveable { mutableIntStateOf(sharedSettingsViewModel.dataStore.getCountry()) }
var countryString by remember { mutableStateOf(countryOptions[selectedCountry]) }
Expand Down Expand Up @@ -180,6 +160,13 @@ fun SmartIdView(

val smartIdChallengeNotificationId = Constant.SmartIdConstants.NOTIFICATION_PERMISSION_CODE

LaunchedEffect(signedContainer) {
cancelAction {
smartIdViewModel.cancelSmartIdWorkRequest(signedContainer)
smartIdViewModel.cancelNotification(smartIdChallengeNotificationId)
}
}

BackHandler {
if (isSigning) {
onError()
Expand Down Expand Up @@ -387,10 +374,6 @@ fun SmartIdView(
roleData = roleDataRequest,
)
}
cancelAction {
smartIdViewModel.cancelSmartIdWorkRequest(signedContainer)
smartIdViewModel.cancelNotification(smartIdChallengeNotificationId)
}
}
}

Expand Down Expand Up @@ -580,7 +563,6 @@ fun SmartIdViewPreview() {
val sharedSettingsViewModel: SharedSettingsViewModel = hiltViewModel()
RIADigiDocTheme {
SmartIdView(
activity = LocalActivity.current as Activity,
sharedSettingsViewModel = sharedSettingsViewModel,
sharedContainerViewModel = sharedContainerViewModel,
isSigning = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale
Expand Down Expand Up @@ -68,9 +66,6 @@ class MobileIdViewModel
private val _dialogError = MutableLiveData(0)
val dialogError: LiveData<Int> = _dialogError

private val _signingInProgress = MutableStateFlow(false)
val signingInProgress: StateFlow<Boolean> = _signingInProgress

private var signingJob: Job? = null

private val faults: ImmutableMap<MobileCertificateResultType, Int> =
Expand Down Expand Up @@ -293,7 +288,6 @@ class MobileIdViewModel

signingJob =
viewModelScope.launch(IO) {
_signingInProgress.value = true
try {
resetValues()
val configurationProvider = configurationRepository.getConfiguration()
Expand Down Expand Up @@ -351,7 +345,6 @@ class MobileIdViewModel
mobileSignService.status.removeObserver(statusObserver)
mobileSignService.response.removeObserver(responseObserver)
}
_signingInProgress.value = false
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Objects
Expand Down Expand Up @@ -75,9 +73,6 @@ class SmartIdViewModel
private val _requestNotificationPermission = MutableSharedFlow<Pair<String, String>>()
val requestNotificationPermission: SharedFlow<Pair<String, String>> = _requestNotificationPermission

private val _signingInProgress = MutableStateFlow(false)
val signingInProgress: StateFlow<Boolean> = _signingInProgress

private var signingJob: Job? = null

private val countries: ImmutableMap<Int, String> =
Expand Down Expand Up @@ -315,7 +310,6 @@ class SmartIdViewModel

signingJob =
viewModelScope.launch(IO) {
_signingInProgress.value = true
try {
resetValues()
val configurationProvider = configurationRepository.getConfiguration()
Expand Down Expand Up @@ -370,7 +364,6 @@ class SmartIdViewModel
smartSignService.status.removeObserver(statusObserver)
smartSignService.response.removeObserver(responseObserver)
}
_signingInProgress.value = false
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ import ee.ria.DigiDoc.network.proxy.ManualProxy
import ee.ria.DigiDoc.network.proxy.ProxySetting
import ee.ria.DigiDoc.utilsLib.signing.TrustManagerUtil
import ee.ria.libdigidocpp.ExternalSigner
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody.Companion.toResponseBody
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Rule
Expand Down Expand Up @@ -2632,4 +2634,50 @@ class MobileSignServiceImplTest {
verify(statusObserver, never()).onChanged(MobileCreateSignatureProcessStatus.GENERAL_ERROR)
verify(containerWrapper, never()).finalizeSignature(any(), any(), any())
}

@Test
fun mobileSignService_processMobileIdRequest_rethrowsCancellationException() =
runTest {
doReturn(midRestServiceClient).whenever(serviceGenerator).createService(
context = context,
sslContext = null,
midSignServiceUrl = request.url,
certBundle = certBundle,
trustManagers = trustManagers,
proxySetting = proxySetting,
manualProxySettings = manualProxy,
)

val call = mock(Call::class.java)
doReturn(call)
.whenever(midRestServiceClient)
.getCertificate(
body = getMobileCertificateRequest,
)

doThrow(CancellationException("Signing cancelled"))
.whenever(call)
.execute()

var cancellation: CancellationException? = null
try {
mobileSignServiceImpl.processMobileIdRequest(
context = context,
signedContainer = signedContainer,
request = request,
roleDataRequest = null,
proxySetting = proxySetting,
manualProxySettings = manualProxy,
certificateBundle = certBundle,
accessTokenPath = "accessTokenPath",
accessTokenPass = "accessTokenPass",
)
} catch (ce: CancellationException) {
cancellation = ce
}

assertNotNull(cancellation)
verify(statusObserver, never()).onChanged(MobileCreateSignatureProcessStatus.GENERAL_ERROR)
verify(statusObserver, never()).onChanged(MobileCreateSignatureProcessStatus.TECHNICAL_ERROR)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import ee.ria.DigiDoc.utilsLib.signing.UUIDUtil
import ee.ria.DigiDoc.utilsLib.text.MessageUtil
import ee.ria.libdigidocpp.Container
import ee.ria.libdigidocpp.ExternalSigner
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
import retrofit2.Call
import retrofit2.Response
Expand Down Expand Up @@ -491,6 +492,9 @@ class MobileSignServiceImpl
// If user has cancelled signing, do not show any message
setStatus(MobileCreateSignatureProcessStatus.USER_CANCELLED)
return
} catch (ce: CancellationException) {
errorLog(logTag, "Mobile-ID signing cancelled", ce)
throw ce
} catch (e: Exception) {
val message = e.message
if (!message.isNullOrEmpty() && message.contains("Too Many Requests")) {
Expand Down
Loading
Loading