Add SignedOutNode, to handle session behind deleted from outside (no support for soft-logout)
This commit is contained in:
committed by
Benoit Marty
parent
0b3fcecbed
commit
5faf706264
@@ -64,6 +64,7 @@ dependencies {
|
||||
testImplementation(libs.test.turbine)
|
||||
testImplementation(projects.libraries.matrix.test)
|
||||
testImplementation(projects.features.networkmonitor.test)
|
||||
testImplementation(projects.libraries.sessionStorage.implMemory)
|
||||
testImplementation(projects.tests.testutils)
|
||||
testImplementation(projects.features.rageshake.test)
|
||||
testImplementation(projects.features.rageshake.impl)
|
||||
|
||||
@@ -42,6 +42,7 @@ import io.element.android.appnav.intent.ResolvedIntent
|
||||
import io.element.android.appnav.root.RootNavStateFlowFactory
|
||||
import io.element.android.appnav.root.RootPresenter
|
||||
import io.element.android.appnav.root.RootView
|
||||
import io.element.android.appnav.signedout.SignedOutNode
|
||||
import io.element.android.features.login.api.oidc.OidcAction
|
||||
import io.element.android.features.login.api.oidc.OidcActionFlow
|
||||
import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint
|
||||
@@ -98,21 +99,22 @@ class RootFlowNode @AssistedInject constructor(
|
||||
.distinctUntilChanged()
|
||||
.onEach { navState ->
|
||||
Timber.v("navState=$navState")
|
||||
when(navState.loggedInState) {
|
||||
when (navState.loggedInState) {
|
||||
is LoggedInState.LoggedIn -> {
|
||||
if(navState.loggedInState.isTokenValid) {
|
||||
if (navState.loggedInState.isTokenValid) {
|
||||
tryToRestoreLatestSession(
|
||||
onSuccess = { sessionId -> switchToLoggedInFlow(sessionId, navState.cacheIndex) },
|
||||
onFailure = { switchToNotLoggedInFlow() }
|
||||
)
|
||||
} else {
|
||||
switchToSignedOutFlow()
|
||||
switchToSignedOutFlow(SessionId((navState.loggedInState.sessionId)))
|
||||
}
|
||||
}
|
||||
LoggedInState.NotLoggedIn -> {
|
||||
switchToNotLoggedInFlow()
|
||||
LoggedInState.NotLoggedIn -> {
|
||||
switchToNotLoggedInFlow()
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
@@ -125,8 +127,8 @@ class RootFlowNode @AssistedInject constructor(
|
||||
backstack.safeRoot(NavTarget.NotLoggedInFlow)
|
||||
}
|
||||
|
||||
private fun switchToSignedOutFlow() {
|
||||
backstack.safeRoot(NavTarget.SignedOutFlow)
|
||||
private fun switchToSignedOutFlow(sessionId: SessionId) {
|
||||
backstack.safeRoot(NavTarget.SignedOutFlow(sessionId))
|
||||
}
|
||||
|
||||
private suspend fun restoreSessionIfNeeded(
|
||||
@@ -191,7 +193,9 @@ class RootFlowNode @AssistedInject constructor(
|
||||
) : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data object SignedOutFlow : NavTarget
|
||||
data class SignedOutFlow(
|
||||
val sessionId: SessionId
|
||||
) : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data object BugReport : NavTarget
|
||||
@@ -212,7 +216,10 @@ class RootFlowNode @AssistedInject constructor(
|
||||
createNode<LoggedInAppScopeFlowNode>(buildContext, plugins = listOf(inputs, callback))
|
||||
}
|
||||
NavTarget.NotLoggedInFlow -> createNode<NotLoggedInFlowNode>(buildContext)
|
||||
NavTarget.SignedOutFlow -> createNode<SignedOutFlowNode>(buildContext)
|
||||
is NavTarget.SignedOutFlow -> {
|
||||
val inputs = SignedOutNode.Inputs(navTarget.sessionId)
|
||||
createNode<SignedOutNode>(buildContext, listOf(inputs))
|
||||
}
|
||||
NavTarget.SplashScreen -> splashNode(buildContext)
|
||||
NavTarget.BugReport -> {
|
||||
val callback = object : BugReportEntryPoint.Callback {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.signedout
|
||||
|
||||
sealed interface SignedOutEvents {
|
||||
data object SignInAgain : SignedOutEvents
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.signedout
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
@ContributesNode(AppScope::class)
|
||||
class SignedOutNode @AssistedInject constructor(
|
||||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
presenterFactory: SignedOutPresenter.Factory,
|
||||
) : Node(buildContext, plugins = plugins) {
|
||||
|
||||
data class Inputs(
|
||||
val sessionId: SessionId,
|
||||
) : NodeInputs
|
||||
|
||||
private val inputs: Inputs = inputs()
|
||||
private val presenter = presenterFactory.create(inputs.sessionId.value)
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val state = presenter.present()
|
||||
SignedOutView(
|
||||
state = state,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.signedout
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SignedOutPresenter @AssistedInject constructor(
|
||||
@Assisted private val sessionId: String, /* Cannot inject SessionId */
|
||||
private val sessionStore: SessionStore,
|
||||
) : Presenter<SignedOutState> {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(sessionId: String): SignedOutPresenter
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun present(): SignedOutState {
|
||||
val sessions by sessionStore.sessionsFlow().collectAsState(initial = emptyList())
|
||||
val signedOutSession by remember {
|
||||
derivedStateOf { sessions.firstOrNull { it.userId == sessionId } }
|
||||
}
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
fun handleEvents(event: SignedOutEvents) {
|
||||
when (event) {
|
||||
SignedOutEvents.SignInAgain -> coroutineScope.launch {
|
||||
sessionStore.removeSession(sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SignedOutState(
|
||||
signedOutSession = signedOutSession,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.signedout
|
||||
|
||||
import io.element.android.libraries.sessionstorage.api.SessionData
|
||||
|
||||
// Do not use default value, so no member get forgotten in the presenters.
|
||||
data class SignedOutState(
|
||||
val signedOutSession: SessionData?,
|
||||
val eventSink: (SignedOutEvents) -> Unit,
|
||||
)
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.signedout
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.sessionstorage.api.LoginType
|
||||
import io.element.android.libraries.sessionstorage.api.SessionData
|
||||
|
||||
open class SignedOutStateProvider : PreviewParameterProvider<SignedOutState> {
|
||||
override val values: Sequence<SignedOutState>
|
||||
get() = sequenceOf(
|
||||
aSignedOutState(),
|
||||
// Add other states here
|
||||
)
|
||||
}
|
||||
|
||||
fun aSignedOutState() = SignedOutState(
|
||||
eventSink = {},
|
||||
signedOutSession = aSessionData()
|
||||
)
|
||||
|
||||
fun aSessionData(
|
||||
sessionId: SessionId = SessionId("@alice:server.org"),
|
||||
isTokenValid: Boolean = false,
|
||||
): SessionData {
|
||||
return SessionData(
|
||||
userId = sessionId.value,
|
||||
deviceId = "aDeviceId",
|
||||
accessToken = "anAccessToken",
|
||||
refreshToken = "aRefreshToken",
|
||||
homeserverUrl = "aHomeserverUrl",
|
||||
oidcData = null,
|
||||
slidingSyncProxy = null,
|
||||
loginTimestamp = null,
|
||||
isTokenValid = isTokenValid,
|
||||
loginType = LoginType.UNKNOWN,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.signedout
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.BiasAlignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
|
||||
import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem
|
||||
import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism
|
||||
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.temporaryColorBgSpecial
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
// TODO i18n, when wording has been approved.
|
||||
@Composable
|
||||
fun SignedOutView(
|
||||
state: SignedOutState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BackHandler(onBack = { state.eventSink(SignedOutEvents.SignInAgain) })
|
||||
HeaderFooterPage(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding(),
|
||||
header = { SignedOutHeader() },
|
||||
content = { SignedOutContent() },
|
||||
footer = {
|
||||
SignedOutFooter(
|
||||
onSignInAgain = { state.eventSink(SignedOutEvents.SignInAgain) },
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SignedOutHeader() {
|
||||
IconTitleSubtitleMolecule(
|
||||
modifier = Modifier.padding(top = 60.dp, bottom = 12.dp),
|
||||
title = "You’re signed out",
|
||||
subTitle = "It can be due to various reasons:",
|
||||
iconImageVector = Icons.Filled.AccountCircle
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SignedOutContent(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
contentAlignment = BiasAlignment(
|
||||
horizontalBias = 0f,
|
||||
verticalBias = -0.4f
|
||||
)
|
||||
) {
|
||||
InfoListOrganism(
|
||||
items = persistentListOf(
|
||||
InfoListItem(
|
||||
message = "You’ve changed your password on another session.",
|
||||
iconComposable = { CheckIcon() },
|
||||
),
|
||||
InfoListItem(
|
||||
message = "You have deleted this session from another session.",
|
||||
iconComposable = { CheckIcon() },
|
||||
),
|
||||
InfoListItem(
|
||||
message = "The administrator of your server has invalidated your access for security reason.",
|
||||
iconComposable = { CheckIcon() },
|
||||
),
|
||||
),
|
||||
textStyle = ElementTheme.typography.fontBodyMdMedium,
|
||||
iconTint = ElementTheme.colors.textPrimary,
|
||||
backgroundColor = ElementTheme.colors.temporaryColorBgSpecial
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CheckIcon(modifier: Modifier = Modifier) {
|
||||
Icon(
|
||||
modifier = modifier
|
||||
.size(20.dp)
|
||||
.background(color = MaterialTheme.colorScheme.background, shape = CircleShape)
|
||||
.padding(2.dp),
|
||||
resourceId = CommonDrawables.ic_compound_check,
|
||||
contentDescription = null,
|
||||
tint = ElementTheme.colors.textActionAccent,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SignedOutFooter(
|
||||
modifier: Modifier = Modifier,
|
||||
onSignInAgain: () -> Unit,
|
||||
) {
|
||||
ButtonColumnMolecule(
|
||||
modifier = modifier,
|
||||
) {
|
||||
Button(
|
||||
text = "Sign in again",
|
||||
onClick = onSignInAgain,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
fun SignedOutViewPreview(
|
||||
@PreviewParameter(SignedOutStateProvider::class) state: SignedOutState,
|
||||
) = ElementPreview {
|
||||
SignedOutView(
|
||||
state = state,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.signedout
|
||||
|
||||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
class SignedOutPresenterTest {
|
||||
@get:Rule
|
||||
val warmUpRule = WarmUpRule()
|
||||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val aSessionData = aSessionData()
|
||||
val sessionStore = InMemorySessionStore().apply {
|
||||
storeData(aSessionData)
|
||||
}
|
||||
val presenter = createPresenter(sessionStore = sessionStore)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.signedOutSession).isEqualTo(aSessionData)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - sign in again`() = runTest {
|
||||
val aSessionData = aSessionData()
|
||||
val sessionStore = InMemorySessionStore().apply {
|
||||
storeData(aSessionData)
|
||||
}
|
||||
val presenter = createPresenter(sessionStore = sessionStore)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.signedOutSession).isEqualTo(aSessionData)
|
||||
assertThat(sessionStore.getAllSessions()).isNotEmpty()
|
||||
initialState.eventSink(SignedOutEvents.SignInAgain)
|
||||
assertThat(awaitItem().signedOutSession).isNull()
|
||||
assertThat(sessionStore.getAllSessions()).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPresenter(
|
||||
sessionId: SessionId = A_SESSION_ID,
|
||||
sessionStore: SessionStore = InMemorySessionStore(),
|
||||
): SignedOutPresenter {
|
||||
return SignedOutPresenter(
|
||||
sessionId = sessionId.value,
|
||||
sessionStore = sessionStore,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -18,5 +18,8 @@ package io.element.android.libraries.sessionstorage.api
|
||||
|
||||
sealed interface LoggedInState {
|
||||
data object NotLoggedIn : LoggedInState
|
||||
data class LoggedIn(val isTokenValid: Boolean) : LoggedInState
|
||||
data class LoggedIn(
|
||||
val sessionId: String,
|
||||
val isTokenValid: Boolean,
|
||||
) : LoggedInState
|
||||
}
|
||||
|
||||
@@ -32,7 +32,10 @@ class InMemorySessionStore : SessionStore {
|
||||
if (it == null) {
|
||||
LoggedInState.NotLoggedIn
|
||||
} else {
|
||||
LoggedInState.LoggedIn(it.isTokenValid)
|
||||
LoggedInState.LoggedIn(
|
||||
sessionId = it.userId,
|
||||
isTokenValid = it.isTokenValid,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,10 @@ class DatabaseSessionStore @Inject constructor(
|
||||
if (it == null) {
|
||||
LoggedInState.NotLoggedIn
|
||||
} else {
|
||||
LoggedInState.LoggedIn((it.isTokenValid ?: 1) == 1L)
|
||||
LoggedInState.LoggedIn(
|
||||
sessionId = it.userId,
|
||||
isTokenValid = (it.isTokenValid ?: 1) == 1L
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user