Browse Source

Extract OIDC to its own module

pull/3298/head
Jorge Martín 1 month ago
parent
commit
ee7a31cace
  1. 2
      appnav/build.gradle.kts
  2. 4
      appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
  3. 4
      appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt
  4. 6
      appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt
  5. 2
      features/login/impl/build.gradle.kts
  6. 18
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt
  7. 10
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt
  8. 6
      features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt
  9. 2
      features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionViewTest.kt
  10. 9
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt
  11. 38
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt
  12. 27
      libraries/oidc/api/build.gradle.kts
  13. 2
      libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt
  14. 6
      libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt
  15. 27
      libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcEntryPoint.kt
  16. 2
      libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt
  17. 71
      libraries/oidc/impl/build.gradle.kts
  18. 2
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/CustomTabAvailabilityChecker.kt
  19. 49
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt
  20. 6
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt
  21. 4
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt
  22. 2
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/CustomTabHandler.kt
  23. 10
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/DefaultOidcActionFlow.kt
  24. 4
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcEvents.kt
  25. 2
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcNode.kt
  26. 4
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt
  27. 2
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcState.kt
  28. 2
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcStateProvider.kt
  29. 4
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt
  30. 2
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcWebViewClient.kt
  31. 2
      libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/WebViewEventListener.kt
  32. 4
      libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParserTest.kt
  33. 4
      libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenterTest.kt
  34. 1
      plugins/src/main/kotlin/extension/DependencyHandleScope.kt

2
appnav/build.gradle.kts

@ -42,6 +42,7 @@ dependencies { @@ -42,6 +42,7 @@ dependencies {
implementation(projects.libraries.architecture)
implementation(projects.libraries.deeplink)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.oidc.api)
implementation(projects.libraries.preferences.api)
implementation(projects.libraries.push.api)
implementation(projects.libraries.pushproviders.api)
@ -66,6 +67,7 @@ dependencies { @@ -66,6 +67,7 @@ dependencies {
testImplementation(libs.test.truth)
testImplementation(libs.test.turbine)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.oidc.impl)
testImplementation(projects.libraries.push.test)
testImplementation(projects.libraries.pushproviders.test)
testImplementation(projects.features.networkmonitor.test)

4
appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt

@ -42,8 +42,6 @@ import io.element.android.appnav.intent.ResolvedIntent @@ -42,8 +42,6 @@ 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.features.login.api.oidc.OidcAction
import io.element.android.features.login.api.oidc.OidcActionFlow
import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint
import io.element.android.features.signedout.api.SignedOutEntryPoint
import io.element.android.features.viewfolder.api.ViewFolderEntryPoint
@ -59,6 +57,8 @@ import io.element.android.libraries.matrix.api.core.SessionId @@ -59,6 +57,8 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.sessionstorage.api.LoggedInState
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcActionFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

4
appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt

@ -17,12 +17,12 @@ @@ -17,12 +17,12 @@
package io.element.android.appnav.intent
import android.content.Intent
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.features.login.api.oidc.OidcIntentResolver
import io.element.android.libraries.deeplink.DeeplinkData
import io.element.android.libraries.deeplink.DeeplinkParser
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcIntentResolver
import timber.log.Timber
import javax.inject.Inject

6
appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt

@ -21,9 +21,6 @@ import android.content.Intent @@ -21,9 +21,6 @@ import android.content.Intent
import android.net.Uri
import androidx.core.net.toUri
import com.google.common.truth.Truth.assertThat
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.features.login.impl.oidc.DefaultOidcIntentResolver
import io.element.android.features.login.impl.oidc.OidcUrlParser
import io.element.android.libraries.deeplink.DeepLinkCreator
import io.element.android.libraries.deeplink.DeeplinkData
import io.element.android.libraries.deeplink.DeeplinkParser
@ -33,6 +30,9 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -33,6 +30,9 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_THREAD_ID
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.impl.DefaultOidcIntentResolver
import io.element.android.libraries.oidc.impl.OidcUrlParser
import io.element.android.tests.testutils.lambda.lambdaError
import org.junit.Assert.assertThrows
import org.junit.Test

2
features/login/impl/build.gradle.kts

@ -50,6 +50,7 @@ dependencies { @@ -50,6 +50,7 @@ dependencies {
implementation(projects.libraries.uiStrings)
implementation(projects.libraries.permissions.api)
implementation(projects.libraries.qrcode)
implementation(projects.libraries.oidc.api)
implementation(libs.androidx.browser)
implementation(platform(libs.network.retrofit.bom))
implementation(libs.network.retrofit)
@ -65,6 +66,7 @@ dependencies { @@ -65,6 +66,7 @@ dependencies {
testImplementation(libs.test.truth)
testImplementation(libs.test.turbine)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.oidc.impl)
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.tests.testutils)
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)

18
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt

@ -36,12 +36,7 @@ import dagger.assisted.AssistedInject @@ -36,12 +36,7 @@ import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.login.api.LoginFlowType
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.features.login.api.oidc.OidcActionFlow
import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource
import io.element.android.features.login.impl.oidc.CustomTabAvailabilityChecker
import io.element.android.features.login.impl.oidc.customtab.CustomTabHandler
import io.element.android.features.login.impl.oidc.webview.OidcNode
import io.element.android.features.login.impl.qrcode.QrCodeLoginFlowNode
import io.element.android.features.login.impl.screens.changeaccountprovider.ChangeAccountProviderNode
import io.element.android.features.login.impl.screens.confirmaccountprovider.ConfirmAccountProviderNode
@ -56,6 +51,9 @@ import io.element.android.libraries.architecture.createNode @@ -56,6 +51,9 @@ import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.auth.OidcDetails
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcActionFlow
import io.element.android.libraries.oidc.api.OidcEntryPoint
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
@ -64,11 +62,10 @@ import kotlinx.parcelize.Parcelize @@ -64,11 +62,10 @@ import kotlinx.parcelize.Parcelize
class LoginFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val customTabAvailabilityChecker: CustomTabAvailabilityChecker,
private val customTabHandler: CustomTabHandler,
private val accountProviderDataSource: AccountProviderDataSource,
private val defaultLoginUserStory: DefaultLoginUserStory,
private val oidcActionFlow: OidcActionFlow,
private val oidcEntryPoint: OidcEntryPoint,
) : BaseFlowNode<LoginFlowNode.NavTarget>(
backstack = BackStack(
initialElement = NavTarget.Root,
@ -146,11 +143,11 @@ class LoginFlowNode @AssistedInject constructor( @@ -146,11 +143,11 @@ class LoginFlowNode @AssistedInject constructor(
)
val callback = object : ConfirmAccountProviderNode.Callback {
override fun onOidcDetails(oidcDetails: OidcDetails) {
if (customTabAvailabilityChecker.supportCustomTab()) {
if (oidcEntryPoint.canUseCustomTab()) {
// In this case open a Chrome Custom tab
activity?.let {
customChromeTabStarted = true
customTabHandler.open(it, darkTheme, oidcDetails.url)
oidcEntryPoint.openUrlInCustomTab(it, darkTheme, oidcDetails.url)
}
} else {
// Fallback to WebView mode
@ -201,8 +198,7 @@ class LoginFlowNode @AssistedInject constructor( @@ -201,8 +198,7 @@ class LoginFlowNode @AssistedInject constructor(
createNode<LoginPasswordNode>(buildContext, plugins = listOf(callback))
}
is NavTarget.OidcView -> {
val input = OidcNode.Inputs(navTarget.oidcDetails)
createNode<OidcNode>(buildContext, plugins = listOf(input))
oidcEntryPoint.createFallbackWebViewNode(this, buildContext, navTarget.oidcDetails.url)
}
is NavTarget.WaitList -> {
val inputs = WaitListNode.Inputs(

10
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt

@ -27,15 +27,15 @@ import androidx.compose.runtime.rememberCoroutineScope @@ -27,15 +27,15 @@ import androidx.compose.runtime.rememberCoroutineScope
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.features.login.impl.DefaultLoginUserStory
import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource
import io.element.android.features.login.impl.error.ChangeServerError
import io.element.android.features.login.impl.oidc.customtab.DefaultOidcActionFlow
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcActionFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -43,7 +43,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( @@ -43,7 +43,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor(
@Assisted private val params: Params,
private val accountProviderDataSource: AccountProviderDataSource,
private val authenticationService: MatrixAuthenticationService,
private val defaultOidcActionFlow: DefaultOidcActionFlow,
private val oidcActionFlow: OidcActionFlow,
private val defaultLoginUserStory: DefaultLoginUserStory,
) : Presenter<ConfirmAccountProviderState> {
data class Params(
@ -65,7 +65,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( @@ -65,7 +65,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor(
}
LaunchedEffect(Unit) {
defaultOidcActionFlow.collect { oidcAction ->
oidcActionFlow.collect { oidcAction ->
if (oidcAction != null) {
onOidcAction(oidcAction, loginFlowAction)
}
@ -133,6 +133,6 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( @@ -133,6 +133,6 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor(
}
}
}
defaultOidcActionFlow.reset()
oidcActionFlow.reset()
}
}

6
features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt

@ -20,10 +20,8 @@ import app.cash.molecule.RecompositionMode @@ -20,10 +20,8 @@ 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.features.login.api.oidc.OidcAction
import io.element.android.features.login.impl.DefaultLoginUserStory
import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource
import io.element.android.features.login.impl.oidc.customtab.DefaultOidcActionFlow
import io.element.android.features.login.impl.util.defaultAccountProvider
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
@ -31,6 +29,8 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER @@ -31,6 +29,8 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER
import io.element.android.libraries.matrix.test.A_HOMESERVER_OIDC
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.impl.customtab.DefaultOidcActionFlow
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.waitForPredicate
import kotlinx.coroutines.test.runTest
@ -274,7 +274,7 @@ class ConfirmAccountProviderPresenterTest { @@ -274,7 +274,7 @@ class ConfirmAccountProviderPresenterTest {
params = params,
accountProviderDataSource = accountProviderDataSource,
authenticationService = matrixAuthenticationService,
defaultOidcActionFlow = defaultOidcActionFlow,
oidcActionFlow = defaultOidcActionFlow,
defaultLoginUserStory = defaultLoginUserStory,
)
}

2
features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionViewTest.kt

@ -217,12 +217,14 @@ class VerifySelfSessionViewTest { @@ -217,12 +217,14 @@ class VerifySelfSessionViewTest {
state: VerifySelfSessionState,
onEnterRecoveryKey: () -> Unit = EnsureNeverCalled(),
onFinished: () -> Unit = EnsureNeverCalled(),
onResetKey: () -> Unit = EnsureNeverCalled(),
) {
setContent {
VerifySelfSessionView(
state = state,
onEnterRecoveryKey = onEnterRecoveryKey,
onFinish = onFinished,
onResetKey = onResetKey,
)
}
}

9
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt

@ -20,13 +20,16 @@ import io.element.android.libraries.matrix.api.encryption.BackupState @@ -20,13 +20,16 @@ import io.element.android.libraries.matrix.api.encryption.BackupState
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle
import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.tests.testutils.simulateLongTask
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
class FakeEncryptionService : EncryptionService {
class FakeEncryptionService(
var startIdentityResetLambda: () -> Result<IdentityResetHandle?> = { error("Not implemented") },
) : EncryptionService {
private var disableRecoveryFailure: Exception? = null
override val backupStateStateFlow: MutableStateFlow<BackupState> = MutableStateFlow(BackupState.UNKNOWN)
override val recoveryStateStateFlow: MutableStateFlow<RecoveryState> = MutableStateFlow(RecoveryState.UNKNOWN)
@ -118,6 +121,10 @@ class FakeEncryptionService : EncryptionService { @@ -118,6 +121,10 @@ class FakeEncryptionService : EncryptionService {
enableRecoveryProgressStateFlow.emit(state)
}
override suspend fun startIdentityReset(): Result<IdentityResetHandle?> {
return startIdentityResetLambda()
}
companion object {
const val FAKE_RECOVERY_KEY = "fake"
}

38
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 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
*
* https://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.libraries.matrix.test.encryption
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle
import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle
class FakeIdentityOidcResetHandle(
override val url: String = "",
var resetOidcLambda: () -> Result<Unit> = { error("Not implemented") }
) : IdentityOidcResetHandle {
override suspend fun resetOidc(): Result<Unit> {
return resetOidcLambda()
}
}
class FakeIdentityPasswordResetHandle(
var resetPasswordLambda: (UserId, String) -> Result<Unit> = { _, _ -> error("Not implemented") }
) : IdentityPasswordResetHandle {
override suspend fun resetPassword(userId: UserId, password: String): Result<Unit> {
return resetPasswordLambda(userId, password)
}
}

27
libraries/oidc/api/build.gradle.kts

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* 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.
*/
plugins {
id("io.element.android-library")
id("kotlin-parcelize")
}
android {
namespace = "io.element.android.libraries.oidc.api"
}
dependencies {
implementation(projects.libraries.architecture)
}

2
features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcAction.kt → libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.api.oidc
package io.element.android.libraries.oidc.api
sealed interface OidcAction {
data object GoBack : OidcAction

6
features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcActionFlow.kt → libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt

@ -14,8 +14,12 @@ @@ -14,8 +14,12 @@
* limitations under the License.
*/
package io.element.android.features.login.api.oidc
package io.element.android.libraries.oidc.api
import kotlinx.coroutines.flow.FlowCollector
interface OidcActionFlow {
fun post(oidcAction: OidcAction)
suspend fun collect(collector: FlowCollector<OidcAction?>)
fun reset()
}

27
libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcEntryPoint.kt

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* Copyright (c) 2024 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
*
* https://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.libraries.oidc.api
import android.app.Activity
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
interface OidcEntryPoint {
fun canUseCustomTab(): Boolean
fun openUrlInCustomTab(activity: Activity, darkTheme: Boolean, url: String)
fun createFallbackWebViewNode(parentNode: Node, buildContext: BuildContext, url: String): Node
}

2
features/login/api/src/main/kotlin/io/element/android/features/login/api/oidc/OidcIntentResolver.kt → libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.api.oidc
package io.element.android.libraries.oidc.api
import android.content.Intent

71
libraries/oidc/impl/build.gradle.kts

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
/*
* Copyright (c) 2022 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.
*/
plugins {
id("io.element.android-compose-library")
alias(libs.plugins.anvil)
id("kotlin-parcelize")
alias(libs.plugins.kotlin.serialization)
}
android {
namespace = "io.element.android.libraries.oidc.impl"
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}
anvil {
generateDaggerFactories.set(true)
}
dependencies {
implementation(projects.anvilannotations)
implementation(projects.appconfig)
anvil(projects.anvilcodegen)
implementation(projects.libraries.core)
implementation(projects.libraries.androidutils)
implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.network)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.testtags)
implementation(projects.libraries.uiStrings)
implementation(projects.libraries.permissions.api)
implementation(projects.libraries.qrcode)
implementation(libs.androidx.browser)
implementation(platform(libs.network.retrofit.bom))
implementation(libs.network.retrofit)
implementation(libs.serialization.json)
api(projects.libraries.oidc.api)
testImplementation(libs.test.junit)
testImplementation(libs.androidx.compose.ui.test.junit)
testImplementation(libs.androidx.test.ext.junit)
testImplementation(libs.coroutines.test)
testImplementation(libs.molecule.runtime)
testImplementation(libs.test.robolectric)
testImplementation(libs.test.truth)
testImplementation(libs.test.turbine)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.tests.testutils)
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
}

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/CustomTabAvailabilityChecker.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/CustomTabAvailabilityChecker.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc
package io.element.android.libraries.oidc.impl
import android.content.Context
import androidx.browser.customtabs.CustomTabsClient

49
libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcEntryPoint.kt

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
/*
* Copyright (c) 2024 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
*
* https://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.libraries.oidc.impl
import android.app.Activity
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.auth.OidcDetails
import io.element.android.libraries.oidc.impl.webview.OidcNode
import io.element.android.libraries.oidc.api.OidcEntryPoint
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class DefaultOidcEntryPoint @Inject constructor(
private val customTabAvailabilityChecker: CustomTabAvailabilityChecker,
) : OidcEntryPoint {
override fun canUseCustomTab(): Boolean {
return customTabAvailabilityChecker.supportCustomTab()
}
override fun openUrlInCustomTab(activity: Activity, darkTheme: Boolean, url: String) {
assert(canUseCustomTab()) { "Custom tab is not supported in this device." }
activity.openUrlInChromeCustomTab(null, darkTheme, url)
}
override fun createFallbackWebViewNode(parentNode: Node, buildContext: BuildContext, url: String): Node {
assert(!canUseCustomTab()) { "Custom tab should be used instead of the fallback node." }
val inputs = OidcNode.Inputs(OidcDetails(url))
return parentNode.createNode<OidcNode>(buildContext, listOf(inputs))
}
}

6
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/DefaultOidcIntentResolver.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt

@ -14,13 +14,13 @@ @@ -14,13 +14,13 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc
package io.element.android.libraries.oidc.impl
import android.content.Intent
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.features.login.api.oidc.OidcIntentResolver
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcIntentResolver
import javax.inject.Inject
@ContributesBinding(AppScope::class)

4
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParser.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt

@ -14,10 +14,10 @@ @@ -14,10 +14,10 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc
package io.element.android.libraries.oidc.impl
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.libraries.matrix.api.auth.OidcConfig
import io.element.android.libraries.oidc.api.OidcAction
import javax.inject.Inject
/**

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/CustomTabHandler.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.customtab
package io.element.android.libraries.oidc.impl.customtab
import android.app.Activity
import android.content.ComponentName

10
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/DefaultOidcActionFlow.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/customtab/DefaultOidcActionFlow.kt

@ -14,13 +14,13 @@ @@ -14,13 +14,13 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.customtab
package io.element.android.libraries.oidc.impl.customtab
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.features.login.api.oidc.OidcActionFlow
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcActionFlow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject
@ -34,11 +34,11 @@ class DefaultOidcActionFlow @Inject constructor() : OidcActionFlow { @@ -34,11 +34,11 @@ class DefaultOidcActionFlow @Inject constructor() : OidcActionFlow {
mutableStateFlow.value = oidcAction
}
suspend fun collect(collector: FlowCollector<OidcAction?>) {
override suspend fun collect(collector: FlowCollector<OidcAction?>) {
mutableStateFlow.collect(collector)
}
fun reset() {
override fun reset() {
mutableStateFlow.value = null
}
}

4
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcEvents.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcEvents.kt

@ -14,9 +14,9 @@ @@ -14,9 +14,9 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.libraries.oidc.api.OidcAction
sealed interface OidcEvents {
data object Cancel : OidcEvents

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcNode.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcNode.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier

4
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenter.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenter.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -25,7 +25,7 @@ import androidx.compose.runtime.setValue @@ -25,7 +25,7 @@ import androidx.compose.runtime.setValue
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcState.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcState.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.auth.OidcDetails

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcStateProvider.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcStateProvider.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncAction

4
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcView.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
import android.webkit.WebView
import androidx.activity.compose.BackHandler
@ -28,11 +28,11 @@ import androidx.compose.runtime.setValue @@ -28,11 +28,11 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.viewinterop.AndroidView
import io.element.android.features.login.impl.oidc.OidcUrlParser
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.designsystem.components.async.AsyncActionView
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.oidc.impl.OidcUrlParser
@Composable
fun OidcView(

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcWebViewClient.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/OidcWebViewClient.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
import android.webkit.WebResourceRequest
import android.webkit.WebView

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/WebViewEventListener.kt → libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/webview/WebViewEventListener.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
fun interface WebViewEventListener {
/**

4
features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/OidcUrlParserTest.kt → libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParserTest.kt

@ -14,11 +14,11 @@ @@ -14,11 +14,11 @@
* limitations under the License.
*/
package io.element.android.features.login.impl.oidc
package io.element.android.libraries.oidc.impl
import com.google.common.truth.Truth.assertThat
import io.element.android.features.login.api.oidc.OidcAction
import io.element.android.libraries.matrix.api.auth.OidcConfig
import io.element.android.libraries.oidc.api.OidcAction
import org.junit.Assert
import org.junit.Test

4
features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt → libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/webview/OidcPresenterTest.kt

@ -16,17 +16,17 @@ @@ -16,17 +16,17 @@
@file:OptIn(ExperimentalCoroutinesApi::class)
package io.element.android.features.login.impl.oidc.webview
package io.element.android.libraries.oidc.impl.webview
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.features.login.api.oidc.OidcAction
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.auth.A_OIDC_DATA
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest

1
plugins/src/main/kotlin/extension/DependencyHandleScope.kt

@ -116,6 +116,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { @@ -116,6 +116,7 @@ fun DependencyHandlerScope.allLibrariesImpl() {
implementation(project(":libraries:mediaviewer:impl"))
implementation(project(":libraries:troubleshoot:impl"))
implementation(project(":libraries:fullscreenintent:impl"))
implementation(project(":libraries:oidc:impl"))
}
fun DependencyHandlerScope.allServicesImpl() {

Loading…
Cancel
Save