Be able to let the user trust several Fingerprints during login flow.

It was the case before, see `LoginViewModel.handleUserAcceptCertificate(...)`
This commit is contained in:
Benoit Marty 2023-03-01 21:17:24 +01:00 committed by Benoit Marty
parent 0df8d54de6
commit 448374fc58
4 changed files with 21 additions and 24 deletions

View File

@ -23,7 +23,7 @@ import javax.inject.Inject
class HomeServerConnectionConfigFactory @Inject constructor() { class HomeServerConnectionConfigFactory @Inject constructor() {
fun create(url: String?, fingerprint: Fingerprint? = null): HomeServerConnectionConfig? { fun create(url: String?, fingerprints: List<Fingerprint>? = null): HomeServerConnectionConfig? {
if (url == null) { if (url == null) {
return null return null
} }
@ -31,13 +31,7 @@ class HomeServerConnectionConfigFactory @Inject constructor() {
return try { return try {
HomeServerConnectionConfig.Builder() HomeServerConnectionConfig.Builder()
.withHomeServerUri(url) .withHomeServerUri(url)
.run { .withAllowedFingerPrints(fingerprints)
if (fingerprint == null) {
this
} else {
withAllowedFingerPrints(listOf(fingerprint))
}
}
.build() .build()
} catch (t: Throwable) { } catch (t: Throwable) {
Timber.e(t) Timber.e(t)

View File

@ -160,6 +160,8 @@ class OnboardingViewModel @AssistedInject constructor(
private var emailVerificationPollingJob: Job? by cancelCurrentOnSet() private var emailVerificationPollingJob: Job? by cancelCurrentOnSet()
private var currentJob: Job? by cancelCurrentOnSet() private var currentJob: Job? by cancelCurrentOnSet()
private val trustedFingerprints = mutableListOf<Fingerprint>()
override fun handle(action: OnboardingAction) { override fun handle(action: OnboardingAction) {
when (action) { when (action) {
is OnboardingAction.SplashAction -> handleSplashAction(action) is OnboardingAction.SplashAction -> handleSplashAction(action)
@ -293,13 +295,14 @@ class OnboardingViewModel @AssistedInject constructor(
private fun handleUserAcceptCertificate(action: OnboardingAction.UserAcceptCertificate) { private fun handleUserAcceptCertificate(action: OnboardingAction.UserAcceptCertificate) {
// It happens when we get the login flow, or during direct authentication. // It happens when we get the login flow, or during direct authentication.
// So alter the homeserver config and retrieve again the login flow // So alter the homeserver config and retrieve again the login flow
trustedFingerprints.add(action.fingerprint)
when (action.retryAction) { when (action.retryAction) {
is OnboardingAction.HomeServerChange -> handleHomeserverChange(action.retryAction, fingerprint = action.fingerprint) is OnboardingAction.HomeServerChange -> handleHomeserverChange(action.retryAction, fingerprints = trustedFingerprints)
is AuthenticateAction.LoginDirect -> is AuthenticateAction.LoginDirect ->
handleDirectLogin( handleDirectLogin(
action.retryAction, action.retryAction,
// Will be replaced by the task // Will be replaced by the task
homeServerConnectionConfigFactory.create("https://dummy.org", action.fingerprint) homeServerConnectionConfigFactory.create("https://dummy.org", trustedFingerprints)
) )
else -> Unit else -> Unit
} }
@ -696,10 +699,10 @@ class OnboardingViewModel @AssistedInject constructor(
private fun handleHomeserverChange( private fun handleHomeserverChange(
action: OnboardingAction.HomeServerChange, action: OnboardingAction.HomeServerChange,
serverTypeOverride: ServerType? = null, serverTypeOverride: ServerType? = null,
fingerprint: Fingerprint? = null, fingerprints: List<Fingerprint>? = null,
postAction: suspend () -> Unit = {}, postAction: suspend () -> Unit = {},
) { ) {
val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl, fingerprint) val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl, fingerprints)
if (homeServerConnectionConfig == null) { if (homeServerConnectionConfig == null) {
// This is invalid // This is invalid
_viewEvents.post(OnboardingViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig"))) _viewEvents.post(OnboardingViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig")))

View File

@ -621,7 +621,7 @@ class OnboardingViewModelTest {
@Test @Test
fun `when editing homeserver errors with certificate error, then emits error`() = runTest { fun `when editing homeserver errors with certificate error, then emits error`() = runTest {
fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprint = null, A_HOMESERVER_CONFIG) fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprints = null, A_HOMESERVER_CONFIG)
fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, AN_UNRECOGNISED_CERTIFICATE_ERROR) fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, AN_UNRECOGNISED_CERTIFICATE_ERROR)
val editAction = OnboardingAction.HomeServerChange.EditHomeServer(A_HOMESERVER_URL) val editAction = OnboardingAction.HomeServerChange.EditHomeServer(A_HOMESERVER_URL)
val test = viewModel.test() val test = viewModel.test()
@ -640,7 +640,7 @@ class OnboardingViewModelTest {
@Test @Test
fun `when selecting homeserver errors with certificate error, then emits error`() = runTest { fun `when selecting homeserver errors with certificate error, then emits error`() = runTest {
fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprint = null, A_HOMESERVER_CONFIG) fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprints = null, A_HOMESERVER_CONFIG)
fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, AN_UNRECOGNISED_CERTIFICATE_ERROR) fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, AN_UNRECOGNISED_CERTIFICATE_ERROR)
val selectAction = OnboardingAction.HomeServerChange.SelectHomeServer(A_HOMESERVER_URL) val selectAction = OnboardingAction.HomeServerChange.SelectHomeServer(A_HOMESERVER_URL)
val test = viewModel.test() val test = viewModel.test()
@ -842,7 +842,7 @@ class OnboardingViewModelTest {
A_HOMESERVER_URL, A_HOMESERVER_URL,
SELECTED_HOMESERVER_STATE, SELECTED_HOMESERVER_STATE,
config = A_HOMESERVER_CONFIG.copy(allowedFingerprints = listOf(A_FINGERPRINT)), config = A_HOMESERVER_CONFIG.copy(allowedFingerprints = listOf(A_FINGERPRINT)),
fingerprint = A_FINGERPRINT, fingerprints = listOf(A_FINGERPRINT),
) )
viewModel.handle(OnboardingAction.UserAcceptCertificate(A_FINGERPRINT, OnboardingAction.HomeServerChange.SelectHomeServer(A_HOMESERVER_URL))) viewModel.handle(OnboardingAction.UserAcceptCertificate(A_FINGERPRINT, OnboardingAction.HomeServerChange.SelectHomeServer(A_HOMESERVER_URL)))
@ -866,7 +866,7 @@ class OnboardingViewModelTest {
A_HOMESERVER_URL, A_HOMESERVER_URL,
SELECTED_HOMESERVER_STATE, SELECTED_HOMESERVER_STATE,
config = A_HOMESERVER_CONFIG.copy(allowedFingerprints = listOf(A_FINGERPRINT)), config = A_HOMESERVER_CONFIG.copy(allowedFingerprints = listOf(A_FINGERPRINT)),
fingerprint = A_FINGERPRINT, fingerprints = listOf(A_FINGERPRINT),
) )
val test = viewModel.test() val test = viewModel.test()
@ -886,7 +886,7 @@ class OnboardingViewModelTest {
@Test @Test
fun `given DirectLogin retry action, when accepting user certificate, then logs in directly`() = runTest { fun `given DirectLogin retry action, when accepting user certificate, then logs in directly`() = runTest {
fakeHomeServerConnectionConfigFactory.givenConfigFor("https://dummy.org", A_FINGERPRINT, A_HOMESERVER_CONFIG) fakeHomeServerConnectionConfigFactory.givenConfigFor("https://dummy.org", listOf(A_FINGERPRINT), A_HOMESERVER_CONFIG)
fakeDirectLoginUseCase.givenSuccessResult(A_DIRECT_LOGIN, config = A_HOMESERVER_CONFIG, result = fakeSession) fakeDirectLoginUseCase.givenSuccessResult(A_DIRECT_LOGIN, config = A_HOMESERVER_CONFIG, result = fakeSession)
givenInitialisesSession(fakeSession) givenInitialisesSession(fakeSession)
val test = viewModel.test() val test = viewModel.test()
@ -1175,16 +1175,16 @@ class OnboardingViewModelTest {
homeserverUrl: String, homeserverUrl: String,
resultingState: SelectedHomeserverState, resultingState: SelectedHomeserverState,
config: HomeServerConnectionConfig = A_HOMESERVER_CONFIG, config: HomeServerConnectionConfig = A_HOMESERVER_CONFIG,
fingerprint: Fingerprint? = null, fingerprints: List<Fingerprint>? = null,
) { ) {
fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprint, config) fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprints, config)
fakeStartAuthenticationFlowUseCase.givenResult(config, StartAuthenticationResult(isHomeserverOutdated = false, resultingState)) fakeStartAuthenticationFlowUseCase.givenResult(config, StartAuthenticationResult(isHomeserverOutdated = false, resultingState))
givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.StartRegistration) givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.StartRegistration)
fakeHomeServerHistoryService.expectUrlToBeAdded(config.homeServerUri.toString()) fakeHomeServerHistoryService.expectUrlToBeAdded(config.homeServerUri.toString())
} }
private fun givenUpdatingHomeserverErrors(homeserverUrl: String, resultingState: SelectedHomeserverState, error: Throwable) { private fun givenUpdatingHomeserverErrors(homeserverUrl: String, resultingState: SelectedHomeserverState, error: Throwable) {
fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprint = null, A_HOMESERVER_CONFIG) fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprints = null, A_HOMESERVER_CONFIG)
fakeStartAuthenticationFlowUseCase.givenResult(A_HOMESERVER_CONFIG, StartAuthenticationResult(isHomeserverOutdated = false, resultingState)) fakeStartAuthenticationFlowUseCase.givenResult(A_HOMESERVER_CONFIG, StartAuthenticationResult(isHomeserverOutdated = false, resultingState))
givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.Error(error)) givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.Error(error))
fakeHomeServerHistoryService.expectUrlToBeAdded(A_HOMESERVER_CONFIG.homeServerUri.toString()) fakeHomeServerHistoryService.expectUrlToBeAdded(A_HOMESERVER_CONFIG.homeServerUri.toString())
@ -1209,13 +1209,13 @@ class OnboardingViewModelTest {
private fun givenHomeserverSelectionFailsWithNetworkError() { private fun givenHomeserverSelectionFailsWithNetworkError() {
fakeContext.givenHasConnection() fakeContext.givenHasConnection()
fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprint = null, A_HOMESERVER_CONFIG) fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprints = null, A_HOMESERVER_CONFIG)
fakeStartAuthenticationFlowUseCase.givenHomeserverUnavailable(A_HOMESERVER_CONFIG) fakeStartAuthenticationFlowUseCase.givenHomeserverUnavailable(A_HOMESERVER_CONFIG)
} }
private fun givenHomeserverSelectionFailsWith(cause: Throwable) { private fun givenHomeserverSelectionFailsWith(cause: Throwable) {
fakeContext.givenHasConnection() fakeContext.givenHasConnection()
fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprint = null, A_HOMESERVER_CONFIG) fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprints = null, A_HOMESERVER_CONFIG)
fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, cause) fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, cause)
} }
} }

View File

@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.network.ssl.Fingerprint
class FakeHomeServerConnectionConfigFactory { class FakeHomeServerConnectionConfigFactory {
val instance: HomeServerConnectionConfigFactory = mockk() val instance: HomeServerConnectionConfigFactory = mockk()
fun givenConfigFor(url: String, fingerprint: Fingerprint? = null, config: HomeServerConnectionConfig) { fun givenConfigFor(url: String, fingerprints: List<Fingerprint>? = null, config: HomeServerConnectionConfig) {
every { instance.create(url, fingerprint) } returns config every { instance.create(url, fingerprints) } returns config
} }
} }