Logout on Unauthorized access (#1864)

This commit is contained in:
Shreyash Borde 2025-05-20 20:34:34 +05:30 committed by GitHub
parent 150df36fad
commit b3c9b3f75c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 80 additions and 3 deletions

View File

@ -0,0 +1,24 @@
/*
* Copyright 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
*/
package org.mifospay.core.common
import kotlinx.coroutines.flow.MutableStateFlow
object GlobalAuthManager {
val isUnauthorized = MutableStateFlow(false)
fun markUnauthorized() {
isUnauthorized.value = true
}
fun reset() {
isUnauthorized.value = false
}
}

View File

@ -22,7 +22,7 @@ fun MifosDialogBox(
title: String,
showDialogState: Boolean,
confirmButtonText: String,
dismissButtonText: String,
dismissButtonText: String? = null,
onConfirm: () -> Unit,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
@ -48,8 +48,10 @@ fun MifosDialogBox(
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text(text = dismissButtonText)
if (!dismissButtonText.isNullOrBlank()) {
TextButton(onClick = onDismiss) {
Text(text = dismissButtonText)
}
}
},
)

View File

@ -13,7 +13,10 @@ import io.ktor.client.HttpClient
import io.ktor.client.plugins.HttpClientPlugin
import io.ktor.client.request.HttpRequestPipeline
import io.ktor.client.request.header
import io.ktor.client.statement.HttpResponsePipeline
import io.ktor.http.HttpStatusCode
import io.ktor.util.AttributeKey
import org.mifospay.core.common.GlobalAuthManager
import org.mifospay.core.datastore.UserPreferencesRepository
class KtorInterceptor(
@ -38,6 +41,13 @@ class KtorInterceptor(
}
}
}
scope.responsePipeline.intercept(HttpResponsePipeline.After) {
if (context.response.status == HttpStatusCode.Unauthorized) {
GlobalAuthManager.markUnauthorized()
}
proceedWith(subject)
}
}
override fun prepare(block: Config.() -> Unit): KtorInterceptor {
@ -75,6 +85,13 @@ class KtorInterceptorRe(
}
}
}
scope.responsePipeline.intercept(HttpResponsePipeline.After) {
if (context.response.status == HttpStatusCode.Unauthorized) {
GlobalAuthManager.markUnauthorized()
}
proceedWith(subject)
}
}
override fun prepare(block: ConfigRe.() -> Unit): KtorInterceptorRe {

View File

@ -10,14 +10,19 @@
package org.mifospay.shared
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.compose.rememberNavController
import org.koin.compose.koinInject
import org.koin.compose.viewmodel.koinViewModel
import org.mifospay.core.common.GlobalAuthManager
import org.mifospay.core.data.util.NetworkMonitor
import org.mifospay.core.data.util.TimeZoneMonitor
import org.mifospay.core.designsystem.component.MifosDialogBox
import org.mifospay.core.designsystem.theme.MifosTheme
import org.mifospay.shared.MainUiState.Success
import org.mifospay.shared.navigation.MifosNavGraph.LOGIN_GRAPH
@ -43,6 +48,35 @@ private fun MifosPayApp(
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val navController = rememberNavController()
var showErrorDialog = remember { mutableStateOf<Boolean>(false) }
val isUnauthorized by GlobalAuthManager.isUnauthorized.collectAsStateWithLifecycle()
LaunchedEffect(isUnauthorized) {
if (isUnauthorized) {
showErrorDialog.value = true
}
}
if (showErrorDialog.value) {
MifosDialogBox(
title = "Unauthorized User",
showDialogState = showErrorDialog.value,
confirmButtonText = "Ok",
onConfirm = {
showErrorDialog.value = false
viewModel.logOut()
navController.navigate(LOGIN_GRAPH) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
GlobalAuthManager.reset()
},
onDismiss = {},
message = "Please login again to continue",
)
}
val navDestination = when (uiState) {
is MainUiState.Loading -> LOGIN_GRAPH
is Success -> if ((uiState as Success).userData.authenticated) {