#307 fix pCloud login in F-Droid
This commit is contained in:
parent
9a1d9b7e61
commit
4f8f817808
@ -4,6 +4,7 @@ import org.cryptomator.data.cloud.crypto.CryptoCloudContentRepositoryFactory;
|
|||||||
import org.cryptomator.data.cloud.dropbox.DropboxCloudContentRepositoryFactory;
|
import org.cryptomator.data.cloud.dropbox.DropboxCloudContentRepositoryFactory;
|
||||||
import org.cryptomator.data.cloud.local.LocalStorageContentRepositoryFactory;
|
import org.cryptomator.data.cloud.local.LocalStorageContentRepositoryFactory;
|
||||||
import org.cryptomator.data.cloud.onedrive.OnedriveCloudContentRepositoryFactory;
|
import org.cryptomator.data.cloud.onedrive.OnedriveCloudContentRepositoryFactory;
|
||||||
|
import org.cryptomator.data.cloud.pcloud.PCloudContentRepositoryFactory;
|
||||||
import org.cryptomator.data.cloud.webdav.WebDavCloudContentRepositoryFactory;
|
import org.cryptomator.data.cloud.webdav.WebDavCloudContentRepositoryFactory;
|
||||||
import org.cryptomator.data.repository.CloudContentRepositoryFactory;
|
import org.cryptomator.data.repository.CloudContentRepositoryFactory;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -23,12 +24,14 @@ public class CloudContentRepositoryFactories implements Iterable<CloudContentRep
|
|||||||
@Inject
|
@Inject
|
||||||
public CloudContentRepositoryFactories(DropboxCloudContentRepositoryFactory dropboxFactory, //
|
public CloudContentRepositoryFactories(DropboxCloudContentRepositoryFactory dropboxFactory, //
|
||||||
OnedriveCloudContentRepositoryFactory oneDriveFactory, //
|
OnedriveCloudContentRepositoryFactory oneDriveFactory, //
|
||||||
|
PCloudContentRepositoryFactory pCloudFactory, //
|
||||||
CryptoCloudContentRepositoryFactory cryptoFactory, //
|
CryptoCloudContentRepositoryFactory cryptoFactory, //
|
||||||
LocalStorageContentRepositoryFactory localStorageFactory, //
|
LocalStorageContentRepositoryFactory localStorageFactory, //
|
||||||
WebDavCloudContentRepositoryFactory webDavFactory) {
|
WebDavCloudContentRepositoryFactory webDavFactory) {
|
||||||
|
|
||||||
factories = asList(dropboxFactory, //
|
factories = asList(dropboxFactory, //
|
||||||
oneDriveFactory, //
|
oneDriveFactory, //
|
||||||
|
pCloudFactory, //
|
||||||
cryptoFactory, //
|
cryptoFactory, //
|
||||||
localStorageFactory, //
|
localStorageFactory, //
|
||||||
webDavFactory);
|
webDavFactory);
|
||||||
|
@ -2,17 +2,34 @@ package org.cryptomator.presentation.presenter
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.accounts.AccountManager
|
import android.accounts.AccountManager
|
||||||
|
import android.content.Intent
|
||||||
|
import android.widget.Toast
|
||||||
import com.dropbox.core.android.Auth
|
import com.dropbox.core.android.Auth
|
||||||
|
import com.pcloud.sdk.AuthorizationActivity
|
||||||
|
import com.pcloud.sdk.AuthorizationData
|
||||||
|
import com.pcloud.sdk.AuthorizationRequest
|
||||||
|
import com.pcloud.sdk.AuthorizationResult
|
||||||
import org.cryptomator.data.cloud.onedrive.OnedriveClientFactory
|
import org.cryptomator.data.cloud.onedrive.OnedriveClientFactory
|
||||||
import org.cryptomator.data.cloud.onedrive.graph.ClientException
|
import org.cryptomator.data.cloud.onedrive.graph.ClientException
|
||||||
import org.cryptomator.data.cloud.onedrive.graph.ICallback
|
import org.cryptomator.data.cloud.onedrive.graph.ICallback
|
||||||
import org.cryptomator.data.util.X509CertificateHelper
|
import org.cryptomator.data.util.X509CertificateHelper
|
||||||
import org.cryptomator.domain.*
|
import org.cryptomator.domain.Cloud
|
||||||
|
import org.cryptomator.domain.CloudType
|
||||||
|
import org.cryptomator.domain.DropboxCloud
|
||||||
|
import org.cryptomator.domain.GoogleDriveCloud
|
||||||
|
import org.cryptomator.domain.OnedriveCloud
|
||||||
|
import org.cryptomator.domain.PCloud
|
||||||
|
import org.cryptomator.domain.WebDavCloud
|
||||||
import org.cryptomator.domain.di.PerView
|
import org.cryptomator.domain.di.PerView
|
||||||
import org.cryptomator.domain.exception.FatalBackendException
|
import org.cryptomator.domain.exception.FatalBackendException
|
||||||
import org.cryptomator.domain.exception.NetworkConnectionException
|
import org.cryptomator.domain.exception.NetworkConnectionException
|
||||||
import org.cryptomator.domain.exception.authentication.*
|
import org.cryptomator.domain.exception.authentication.AuthenticationException
|
||||||
|
import org.cryptomator.domain.exception.authentication.WebDavCertificateUntrustedAuthenticationException
|
||||||
|
import org.cryptomator.domain.exception.authentication.WebDavNotSupportedException
|
||||||
|
import org.cryptomator.domain.exception.authentication.WebDavServerNotFoundException
|
||||||
|
import org.cryptomator.domain.exception.authentication.WrongCredentialsException
|
||||||
import org.cryptomator.domain.usecases.cloud.AddOrChangeCloudConnectionUseCase
|
import org.cryptomator.domain.usecases.cloud.AddOrChangeCloudConnectionUseCase
|
||||||
|
import org.cryptomator.domain.usecases.cloud.GetCloudsUseCase
|
||||||
import org.cryptomator.domain.usecases.cloud.GetUsernameUseCase
|
import org.cryptomator.domain.usecases.cloud.GetUsernameUseCase
|
||||||
import org.cryptomator.generator.Callback
|
import org.cryptomator.generator.Callback
|
||||||
import org.cryptomator.presentation.BuildConfig
|
import org.cryptomator.presentation.BuildConfig
|
||||||
@ -20,23 +37,32 @@ import org.cryptomator.presentation.R
|
|||||||
import org.cryptomator.presentation.exception.ExceptionHandlers
|
import org.cryptomator.presentation.exception.ExceptionHandlers
|
||||||
import org.cryptomator.presentation.exception.PermissionNotGrantedException
|
import org.cryptomator.presentation.exception.PermissionNotGrantedException
|
||||||
import org.cryptomator.presentation.intent.AuthenticateCloudIntent
|
import org.cryptomator.presentation.intent.AuthenticateCloudIntent
|
||||||
import org.cryptomator.presentation.model.*
|
import org.cryptomator.presentation.model.CloudModel
|
||||||
|
import org.cryptomator.presentation.model.CloudTypeModel
|
||||||
|
import org.cryptomator.presentation.model.ProgressModel
|
||||||
|
import org.cryptomator.presentation.model.ProgressStateModel
|
||||||
|
import org.cryptomator.presentation.model.WebDavCloudModel
|
||||||
import org.cryptomator.presentation.model.mappers.CloudModelMapper
|
import org.cryptomator.presentation.model.mappers.CloudModelMapper
|
||||||
import org.cryptomator.presentation.ui.activity.view.AuthenticateCloudView
|
import org.cryptomator.presentation.ui.activity.view.AuthenticateCloudView
|
||||||
import org.cryptomator.presentation.workflow.*
|
import org.cryptomator.presentation.workflow.ActivityResult
|
||||||
|
import org.cryptomator.presentation.workflow.AddExistingVaultWorkflow
|
||||||
|
import org.cryptomator.presentation.workflow.CreateNewVaultWorkflow
|
||||||
|
import org.cryptomator.presentation.workflow.PermissionsResult
|
||||||
|
import org.cryptomator.presentation.workflow.Workflow
|
||||||
import org.cryptomator.util.ExceptionUtil
|
import org.cryptomator.util.ExceptionUtil
|
||||||
import org.cryptomator.util.crypto.CredentialCryptor
|
import org.cryptomator.util.crypto.CredentialCryptor
|
||||||
import timber.log.Timber
|
|
||||||
import java.security.cert.CertificateEncodingException
|
import java.security.cert.CertificateEncodingException
|
||||||
import java.security.cert.CertificateException
|
import java.security.cert.CertificateException
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class AuthenticateCloudPresenter @Inject constructor( //
|
class AuthenticateCloudPresenter @Inject constructor( //
|
||||||
exceptionHandlers: ExceptionHandlers, //
|
exceptionHandlers: ExceptionHandlers, //
|
||||||
private val cloudModelMapper: CloudModelMapper, //
|
private val cloudModelMapper: CloudModelMapper, //
|
||||||
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
||||||
|
private val getCloudsUseCase: GetCloudsUseCase, //
|
||||||
private val getUsernameUseCase: GetUsernameUseCase, //
|
private val getUsernameUseCase: GetUsernameUseCase, //
|
||||||
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
||||||
private val createNewVaultWorkflow: CreateNewVaultWorkflow) : Presenter<AuthenticateCloudView>(exceptionHandlers) {
|
private val createNewVaultWorkflow: CreateNewVaultWorkflow) : Presenter<AuthenticateCloudView>(exceptionHandlers) {
|
||||||
@ -44,6 +70,7 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
private val strategies = arrayOf( //
|
private val strategies = arrayOf( //
|
||||||
DropboxAuthStrategy(), //
|
DropboxAuthStrategy(), //
|
||||||
OnedriveAuthStrategy(), //
|
OnedriveAuthStrategy(), //
|
||||||
|
PCloudAuthStrategy(), //
|
||||||
WebDAVAuthStrategy(), //
|
WebDAVAuthStrategy(), //
|
||||||
LocalStorageAuthStrategy() //
|
LocalStorageAuthStrategy() //
|
||||||
)
|
)
|
||||||
@ -221,6 +248,102 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inner class PCloudAuthStrategy : AuthStrategy {
|
||||||
|
|
||||||
|
private var authenticationStarted = false
|
||||||
|
|
||||||
|
override fun supports(cloud: CloudModel): Boolean {
|
||||||
|
return cloud.cloudType() == CloudTypeModel.PCLOUD
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resumed(intent: AuthenticateCloudIntent) {
|
||||||
|
when {
|
||||||
|
ExceptionUtil.contains(intent.error(), WrongCredentialsException::class.java) -> {
|
||||||
|
if (!authenticationStarted) {
|
||||||
|
startAuthentication()
|
||||||
|
Toast.makeText(
|
||||||
|
context(),
|
||||||
|
String.format(getString(R.string.error_authentication_failed_re_authenticate), intent.cloud().username()),
|
||||||
|
Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Timber.tag("AuthicateCloudPrester").e(intent.error())
|
||||||
|
failAuthentication(intent.cloud().name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startAuthentication() {
|
||||||
|
authenticationStarted = true
|
||||||
|
val authIntent: Intent = AuthorizationActivity.createIntent(
|
||||||
|
context(),
|
||||||
|
AuthorizationRequest.create()
|
||||||
|
.setType(AuthorizationRequest.Type.TOKEN)
|
||||||
|
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
|
||||||
|
.setForceAccessApproval(true)
|
||||||
|
.addPermission("manageshares")
|
||||||
|
.build())
|
||||||
|
requestActivityResult(ActivityResultCallbacks.pCloudReAuthenticationFinished(), //
|
||||||
|
authIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback
|
||||||
|
fun pCloudReAuthenticationFinished(activityResult: ActivityResult) {
|
||||||
|
val authData: AuthorizationData = AuthorizationActivity.getResult(activityResult.intent())
|
||||||
|
val result: AuthorizationResult = authData.result
|
||||||
|
|
||||||
|
when (result) {
|
||||||
|
AuthorizationResult.ACCESS_GRANTED -> {
|
||||||
|
val accessToken: String = CredentialCryptor //
|
||||||
|
.getInstance(context()) //
|
||||||
|
.encrypt(authData.token)
|
||||||
|
val pCloudSkeleton: PCloud = PCloud.aPCloud() //
|
||||||
|
.withAccessToken(accessToken)
|
||||||
|
.withUrl(authData.apiHost)
|
||||||
|
.build();
|
||||||
|
getUsernameUseCase //
|
||||||
|
.withCloud(pCloudSkeleton) //
|
||||||
|
.run(object : DefaultResultHandler<String>() {
|
||||||
|
override fun onSuccess(username: String?) {
|
||||||
|
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
AuthorizationResult.ACCESS_DENIED -> {
|
||||||
|
Timber.tag("CloudConnListPresenter").e("Account access denied")
|
||||||
|
view?.showMessage(String.format(getString(R.string.screen_authenticate_auth_authentication_failed), getString(R.string.cloud_names_pcloud)))
|
||||||
|
}
|
||||||
|
AuthorizationResult.AUTH_ERROR -> {
|
||||||
|
Timber.tag("CloudConnListPresenter").e("""Account access grant error: ${authData.errorMessage}""".trimIndent())
|
||||||
|
view?.showMessage(String.format(getString(R.string.screen_authenticate_auth_authentication_failed), getString(R.string.cloud_names_pcloud)))
|
||||||
|
}
|
||||||
|
AuthorizationResult.CANCELLED -> {
|
||||||
|
Timber.tag("CloudConnListPresenter").i("Account access grant cancelled")
|
||||||
|
view?.showMessage(String.format(getString(R.string.screen_authenticate_auth_authentication_failed), getString(R.string.cloud_names_pcloud)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun prepareForSavingPCloud(cloud: PCloud) {
|
||||||
|
getCloudsUseCase //
|
||||||
|
.withCloudType(cloud.type()) //
|
||||||
|
.run(object : DefaultResultHandler<List<Cloud>>() {
|
||||||
|
override fun onSuccess(clouds: List<Cloud>) {
|
||||||
|
clouds.firstOrNull {
|
||||||
|
(it as PCloud).username() == cloud.username()
|
||||||
|
}?.let {
|
||||||
|
it as PCloud
|
||||||
|
succeedAuthenticationWith(PCloud.aCopyOf(it) //
|
||||||
|
.withUrl(cloud.url())
|
||||||
|
.withAccessToken(cloud.accessToken())
|
||||||
|
.build())
|
||||||
|
} ?: succeedAuthenticationWith(cloud)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private inner class WebDAVAuthStrategy : AuthStrategy {
|
private inner class WebDAVAuthStrategy : AuthStrategy {
|
||||||
|
|
||||||
override fun supports(cloud: CloudModel): Boolean {
|
override fun supports(cloud: CloudModel): Boolean {
|
||||||
@ -342,6 +465,6 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
unsubscribeOnDestroy(addOrChangeCloudConnectionUseCase, getUsernameUseCase)
|
unsubscribeOnDestroy(addOrChangeCloudConnectionUseCase, getCloudsUseCase, getUsernameUseCase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user