Login: check login flow - step 1

This commit is contained in:
Benoit Marty 2019-09-13 11:08:54 +02:00
parent a47a3ead1f
commit db8ea0f5e8
8 changed files with 99 additions and 18 deletions

View File

@ -21,12 +21,18 @@ import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
/**
* This interface defines methods to authenticate to a matrix server.
*/
interface Authenticator {
/**
* Request the supported login flows for this homeserver
*/
fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResponse>): Cancelable
/**
* @param homeServerConnectionConfig this param is used to configure the Homeserver
* @param login the login field

View File

@ -17,10 +17,12 @@
package im.vector.matrix.android.internal.auth
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
import im.vector.matrix.android.internal.auth.data.PasswordLoginParams
import im.vector.matrix.android.internal.network.NetworkConstants
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.POST
@ -29,6 +31,13 @@ import retrofit2.http.POST
*/
internal interface AuthAPI {
/**
* Get the supported login flow
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-login
*/
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
fun getLoginFlows(): Call<LoginFlowResponse>
/**
* Pass params to the server for the current login phase.
* Set all the timeouts to 1 minute

View File

@ -25,6 +25,7 @@ import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.SessionManager
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
import im.vector.matrix.android.internal.auth.data.PasswordLoginParams
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
import im.vector.matrix.android.internal.di.Unauthenticated
@ -62,11 +63,20 @@ internal class DefaultAuthenticator @Inject constructor(@Unauthenticated
return sessionManager.getOrCreateSession(sessionParams)
}
override fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResponse>): Cancelable {
val job = GlobalScope.launch(coroutineDispatchers.main) {
val result = runCatching {
getLoginFlowInternal(homeServerConnectionConfig)
}
result.foldToCallback(callback)
}
return CancelableCoroutine(job)
}
override fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig,
login: String,
password: String,
callback: MatrixCallback<Session>): Cancelable {
val job = GlobalScope.launch(coroutineDispatchers.main) {
val sessionOrFailure = runCatching {
authenticate(homeServerConnectionConfig, login, password)
@ -74,7 +84,14 @@ internal class DefaultAuthenticator @Inject constructor(@Unauthenticated
sessionOrFailure.foldToCallback(callback)
}
return CancelableCoroutine(job)
}
private suspend fun getLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig) = withContext(coroutineDispatchers.io) {
val authAPI = buildAuthAPI(homeServerConnectionConfig)
executeRequest<LoginFlowResponse> {
apiCall = authAPI.getLoginFlows()
}
}
private suspend fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig,

View File

@ -20,7 +20,7 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
internal data class LoginFlowResponse(
data class LoginFlowResponse(
@Json(name = "flows")
val flows: List<InteractiveAuthenticationFlow>
)

View File

@ -35,7 +35,7 @@ internal object NetworkModule {
@Provides
@JvmStatic
fun providesHttpLogingInterceptor(): HttpLoggingInterceptor {
fun providesHttpLoggingInterceptor(): HttpLoggingInterceptor {
val logger = FormattedJsonHttpLogger()
val interceptor = HttpLoggingInterceptor(logger)
interceptor.level = BuildConfig.OKHTTP_LOGGING_LEVEL

View File

@ -128,6 +128,28 @@ class LoginFragment : VectorBaseFragment() {
}
override fun invalidate() = withState(viewModel) { state ->
when (state.asyncHomeServerLoginFlowRequest) {
is Loading -> {
progressBar.isVisible = true
touchArea.isVisible = true
passwordShown = false
renderPasswordField()
}
is Fail -> {
progressBar.isVisible = false
touchArea.isVisible = false
Toast.makeText(requireActivity(), "Authenticate failure: ${state.asyncHomeServerLoginFlowRequest.error}", Toast.LENGTH_LONG).show()
}
is Success -> {
progressBar.isVisible = false
touchArea.isVisible = false
// Check login flow
// TODO
}
}
when (state.asyncLoginAction) {
is Loading -> {
progressBar.isVisible = true

View File

@ -25,6 +25,7 @@ import im.vector.matrix.android.api.auth.Authenticator
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
import im.vector.riotx.core.di.ActiveSessionHolder
import im.vector.riotx.core.extensions.configureAndStart
import im.vector.riotx.core.platform.VectorViewModel
@ -104,6 +105,8 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
}
private fun handleUpdateHomeserver(action: LoginActions.UpdateHomeServer) {
currentTask?.cancel()
Try {
val homeServerUri = action.homeServerUrl
homeServerConnectionConfig = HomeServerConnectionConfig.Builder()
@ -111,22 +114,49 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
.build()
}
val homeServerConnectionConfigFinal = homeServerConnectionConfig
// TODO Do request
if (homeServerConnectionConfigFinal == null) {
// This is invalid
setState {
copy(
asyncHomeServerLoginFlowRequest = Fail(Throwable("Baf format"))
)
}
} else {
/*
currentTask?.cancel()
setState {
copy(
asyncHomeServerLoginFlowRequest = Loading()
)
}
currentTask = authenticator.getLoginFlow(homeServerConnectionConfigFinal, object : MatrixCallback<LoginFlowResponse> {
override fun onFailure(failure: Throwable) {
setState {
copy(
asyncHomeServerLoginFlowRequest = Fail(failure)
)
}
}
override fun onSuccess(data: LoginFlowResponse) {
setState {
copy(
asyncHomeServerLoginFlowRequest = Success(data)
)
}
handleLoginFlowResponse(data)
}
})
setState {
copy(
asyncHomeServerLoginFlowRequest = Loading()
)
}
}
private fun handleLoginFlowResponse(loginFlowResponse: LoginFlowResponse) {
// TODO currentTask =
*/
}

View File

@ -19,12 +19,9 @@ package im.vector.riotx.features.login
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Uninitialized
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
data class LoginViewState(
val asyncLoginAction: Async<Unit> = Uninitialized,
val asyncHomeServerLoginFlowRequest: Async<LoginFlowResult> = Uninitialized
val asyncHomeServerLoginFlowRequest: Async<LoginFlowResponse> = Uninitialized
) : MvRxState
// TODO Remove
data class LoginFlowResult(val remover: Boolean)