refactor(user-settings, auth, observability): Refactor to use SecondFactorProof instead of the duplicate SecondFactorFido.kt.

This commit is contained in:
Mateusz Armatys
2024-06-26 17:45:26 +02:00
parent d4f0d5544d
commit d6e61bcd18
67 changed files with 645 additions and 651 deletions
+30 -1
View File
@@ -157,7 +157,10 @@ public final class me/proton/core/auth/fido/domain/entity/Fido2RegisteredKey$Com
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class me/proton/core/auth/fido/domain/entity/SecondFactorFido {
public abstract class me/proton/core/auth/fido/domain/entity/SecondFactorProof {
}
public final class me/proton/core/auth/fido/domain/entity/SecondFactorProof$Fido2 : me/proton/core/auth/fido/domain/entity/SecondFactorProof {
public fun <init> (Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialRequestOptions;[B[B[B[B)V
public final fun getAuthenticatorData ()[B
public final fun getClientData ()[B
@@ -166,6 +169,32 @@ public final class me/proton/core/auth/fido/domain/entity/SecondFactorFido {
public final fun getSignature ()[B
}
public final class me/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorCode : me/proton/core/auth/fido/domain/entity/SecondFactorProof {
public fun <init> (Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorCode;
public static synthetic fun copy$default (Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorCode;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorCode;
public fun equals (Ljava/lang/Object;)Z
public final fun getCode ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorSignature : me/proton/core/auth/fido/domain/entity/SecondFactorProof {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorSignature;
public static synthetic fun copy$default (Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorSignature;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$SecondFactorSignature;
public fun equals (Ljava/lang/Object;)Z
public final fun getClientData ()Ljava/lang/String;
public final fun getKeyHandle ()Ljava/lang/String;
public final fun getSignatureData ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/fido/domain/ext/Fido2AuthenticationExtensionsClientInputsExtKt {
public static final fun toJson (Lme/proton/core/auth/fido/domain/entity/Fido2AuthenticationExtensionsClientInputs;)Lkotlinx/serialization/json/JsonObject;
}
@@ -1,27 +0,0 @@
/*
* Copyright (c) 2024 Proton Technologies AG
* This file is part of Proton AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.auth.fido.domain.entity
public class SecondFactorFido(
public val publicKeyOptions: Fido2PublicKeyCredentialRequestOptions,
public val clientData: ByteArray,
public val authenticatorData: ByteArray,
public val signature: ByteArray,
public val credentialID: ByteArray
)
@@ -16,30 +16,28 @@
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.auth.domain.entity
package me.proton.core.auth.fido.domain.entity
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
sealed class SecondFactorProof {
public sealed class SecondFactorProof {
/**
* The 2FA code here is string, because the same will be used for recovery code (which happens on the same route).
*/
data class SecondFactorCode(
public data class SecondFactorCode(
val code: String
) : SecondFactorProof()
data class SecondFactorSignature(
public data class SecondFactorSignature(
val keyHandle: String,
val clientData: String,
val signatureData: String
) : SecondFactorProof()
class Fido2(
val publicKeyOptions: Fido2PublicKeyCredentialRequestOptions,
val clientData: ByteArray,
val authenticatorData: ByteArray,
val signature: ByteArray,
val credentialID: ByteArray
public class Fido2(
public val publicKeyOptions: Fido2PublicKeyCredentialRequestOptions,
public val clientData: ByteArray,
public val authenticatorData: ByteArray,
public val signature: ByteArray,
public val credentialID: ByteArray
) : SecondFactorProof()
}
+4 -3
View File
@@ -474,7 +474,9 @@ public final class me/proton/core/auth/data/api/request/SecondFactorRequest$Comp
}
public final class me/proton/core/auth/data/api/request/SecondFactorRequestKt {
public static final fun toFido2Request (Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;)Lme/proton/core/auth/data/api/request/Fido2Request;
public static final fun toFido2Request (Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$Fido2;)Lme/proton/core/auth/data/api/request/Fido2Request;
public static final fun toSecondFactorCode (Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)Ljava/lang/String;
public static final fun toSecondFactorFido (Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)Lme/proton/core/auth/data/api/request/Fido2Request;
}
public final class me/proton/core/auth/data/api/request/UniversalTwoFactorRequest {
@@ -823,7 +825,6 @@ public final class me/proton/core/auth/data/api/response/SessionResponse$Compani
public final class me/proton/core/auth/data/feature/IsFido2EnabledImpl : me/proton/core/featureflag/data/IsFeatureFlagEnabledImpl, me/proton/core/auth/domain/feature/IsFido2Enabled {
public fun <init> (Landroid/content/Context;Lme/proton/core/featureflag/domain/FeatureFlagManager;Ljava/util/Optional;)V
public fun invoke (Lme/proton/core/domain/entity/UserId;)Z
public fun isLocalEnabled ()Z
}
@@ -843,7 +844,7 @@ public final class me/proton/core/auth/data/repository/AuthRepositoryImpl : me/p
public fun performLogin (Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun performLoginLess (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun performLoginSso (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun performSecondFactor (Lme/proton/core/network/domain/session/SessionId;Lme/proton/core/auth/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun performSecondFactor (Lme/proton/core/network/domain/session/SessionId;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun randomModulus (Lme/proton/core/network/domain/session/SessionId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun refreshSession (Lme/proton/core/network/domain/session/Session;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun requestSession (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+1 -1
View File
@@ -29,7 +29,7 @@ protonBuild {
}
protonCoverage {
branchCoveragePercentage.set(60)
branchCoveragePercentage.set(57)
lineCoveragePercentage.set(60)
}
@@ -24,7 +24,7 @@ import kotlinx.serialization.Serializable
import me.proton.core.auth.data.api.fido2.AuthenticationOptionsData
import me.proton.core.auth.data.api.fido2.PublicKeyCredentialDescriptorData
import me.proton.core.auth.data.api.fido2.PublicKeyCredentialRequestOptionsResponse
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.auth.fido.domain.ext.toJson
@Serializable
@@ -87,7 +87,7 @@ data class Fido2Request(
}
@OptIn(ExperimentalUnsignedTypes::class)
fun SecondFactorFido.toFido2Request(): Fido2Request {
fun SecondFactorProof.Fido2.toFido2Request(): Fido2Request {
val optionsData = AuthenticationOptionsData(
PublicKeyCredentialRequestOptionsResponse(
challenge = publicKeyOptions.challenge,
@@ -114,3 +114,9 @@ fun SecondFactorFido.toFido2Request(): Fido2Request {
}
private fun ByteArray.toBase64(): String = Base64.encodeToString(this, Base64.NO_WRAP)
fun SecondFactorProof?.toSecondFactorCode(): String? = if (this is SecondFactorProof.SecondFactorCode) code else null
fun SecondFactorProof?.toSecondFactorFido(): Fido2Request? =
if (this is SecondFactorProof.Fido2) toFido2Request() else null
@@ -40,10 +40,10 @@ import me.proton.core.auth.domain.entity.AuthInfo
import me.proton.core.auth.domain.entity.AuthIntent
import me.proton.core.auth.domain.entity.Modulus
import me.proton.core.auth.domain.entity.ScopeInfo
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.entity.SessionInfo
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.challenge.data.frame.ChallengeFrame
import me.proton.core.challenge.domain.entity.ChallengeFrameDetails
import me.proton.core.challenge.domain.framePrefix
@@ -33,11 +33,11 @@ import me.proton.core.auth.data.api.response.SecondFactorResponse
import me.proton.core.auth.data.api.response.SessionResponse
import me.proton.core.auth.domain.entity.AuthInfo
import me.proton.core.auth.domain.entity.ScopeInfo
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.entity.SessionInfo
import me.proton.core.auth.domain.exception.InvalidServerAuthenticationException
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.challenge.data.frame.ChallengeFrame
import me.proton.core.challenge.domain.entity.ChallengeFrameDetails
import me.proton.core.crypto.common.srp.SrpProofs
+3 -41
View File
@@ -143,44 +143,6 @@ public final class me/proton/core/auth/domain/entity/SecondFactorMethod : java/l
public static fun values ()[Lme/proton/core/auth/domain/entity/SecondFactorMethod;
}
public abstract class me/proton/core/auth/domain/entity/SecondFactorProof {
}
public final class me/proton/core/auth/domain/entity/SecondFactorProof$Fido2 : me/proton/core/auth/domain/entity/SecondFactorProof {
public fun <init> (Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialRequestOptions;[B[B[B[B)V
public final fun getAuthenticatorData ()[B
public final fun getClientData ()[B
public final fun getCredentialID ()[B
public final fun getPublicKeyOptions ()Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialRequestOptions;
public final fun getSignature ()[B
}
public final class me/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorCode : me/proton/core/auth/domain/entity/SecondFactorProof {
public fun <init> (Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lme/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorCode;
public static synthetic fun copy$default (Lme/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorCode;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorCode;
public fun equals (Ljava/lang/Object;)Z
public final fun getCode ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorSignature : me/proton/core/auth/domain/entity/SecondFactorProof {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lme/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorSignature;
public static synthetic fun copy$default (Lme/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorSignature;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/auth/domain/entity/SecondFactorProof$SecondFactorSignature;
public fun equals (Ljava/lang/Object;)Z
public final fun getClientData ()Ljava/lang/String;
public final fun getKeyHandle ()Ljava/lang/String;
public final fun getSignatureData ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/domain/entity/SessionDetailsExtKt {
public static final fun getFido2AuthenticationOptions (Lme/proton/core/account/domain/entity/SessionDetails;)Lme/proton/core/auth/fido/domain/entity/Fido2AuthenticationOptions;
}
@@ -240,7 +202,7 @@ public abstract interface class me/proton/core/auth/domain/repository/AuthReposi
public abstract fun performLogin (Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun performLoginLess (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun performLoginSso (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun performSecondFactor (Lme/proton/core/network/domain/session/SessionId;Lme/proton/core/auth/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun performSecondFactor (Lme/proton/core/network/domain/session/SessionId;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun randomModulus (Lme/proton/core/network/domain/session/SessionId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun refreshSession (Lme/proton/core/network/domain/session/Session;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun requestSession (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -352,7 +314,7 @@ public final class me/proton/core/auth/domain/usecase/PerformLogout {
public final class me/proton/core/auth/domain/usecase/PerformSecondFactor {
public fun <init> (Lme/proton/core/auth/domain/repository/AuthRepository;)V
public final fun invoke (Lme/proton/core/network/domain/session/SessionId;Lme/proton/core/auth/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun invoke (Lme/proton/core/network/domain/session/SessionId;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/proton/core/auth/domain/usecase/PostLoginAccountSetup {
@@ -574,7 +536,7 @@ public final class me/proton/core/auth/domain/usecase/scopes/ObtainLockedScope {
public final class me/proton/core/auth/domain/usecase/scopes/ObtainPasswordScope {
public fun <init> (Lme/proton/core/auth/domain/repository/AuthRepository;Lme/proton/core/user/domain/repository/UserRepository;Lme/proton/core/crypto/common/context/CryptoContext;)V
public final fun invoke (Lme/proton/core/domain/entity/UserId;Lme/proton/core/network/domain/session/SessionId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun invoke (Lme/proton/core/domain/entity/UserId;Lme/proton/core/network/domain/session/SessionId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/proton/core/auth/domain/usecase/scopes/RemoveSecurityScopes {
@@ -21,8 +21,8 @@ package me.proton.core.auth.domain.repository
import me.proton.core.auth.domain.entity.AuthInfo
import me.proton.core.auth.domain.entity.Modulus
import me.proton.core.auth.domain.entity.ScopeInfo
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.entity.SessionInfo
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.challenge.domain.entity.ChallengeFrameDetails
import me.proton.core.crypto.common.srp.SrpProofs
import me.proton.core.network.domain.ApiResult
@@ -19,8 +19,8 @@
package me.proton.core.auth.domain.usecase
import me.proton.core.auth.domain.entity.ScopeInfo
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.network.domain.session.SessionId
import javax.inject.Inject
@@ -19,7 +19,7 @@
package me.proton.core.auth.domain.usecase.scopes
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.keystore.decrypt
@@ -39,8 +39,7 @@ class ObtainPasswordScope @Inject constructor(
sessionId: SessionId,
username: String,
password: EncryptedString,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): Boolean {
val authInfo = authRepository.getAuthInfoSrp(
sessionId = sessionId,
@@ -59,8 +58,7 @@ class ObtainPasswordScope @Inject constructor(
userId,
clientProofs,
authInfo.srpSession,
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido
secondFactorProof
)
}
}
@@ -23,8 +23,8 @@ import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import me.proton.core.auth.domain.entity.ScopeInfo
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.network.domain.ApiException
import me.proton.core.network.domain.ApiResult
import me.proton.core.network.domain.session.SessionId
@@ -25,6 +25,7 @@ import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import me.proton.core.auth.domain.entity.AuthInfo
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.srp.SrpCrypto
@@ -56,7 +57,7 @@ class ObtainPasswordScopeTest {
private val testUsername = "test-username"
private val testPassword = "test-password"
private val testPasswordEncrypted = "test-password-encrypted"
private val test2FACode = "test-2fa"
private val test2FACode = SecondFactorProof.SecondFactorCode("test-2fa")
private val testUserId = UserId(testUserIdString)
private val testSessionId = SessionId(testSessionIdString)
private val testModulus = "test-modulus"
@@ -102,7 +103,6 @@ class ObtainPasswordScopeTest {
testUserId,
testSrpProofs,
authInfoResult.srpSession,
null,
null
)
} returns true
@@ -111,7 +111,7 @@ class ObtainPasswordScopeTest {
@Test
fun testUnlockingPasswordNo2FASuccess() = runTest {
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, null, null)
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, null)
coVerify { authRepository.getAuthInfoSrp(testSessionId, testUsername) }
assertTrue(result)
@@ -124,11 +124,10 @@ class ObtainPasswordScopeTest {
testUserId,
testSrpProofs,
authInfoResult.srpSession,
test2FACode,
null
test2FACode
)
} returns true
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, test2FACode, null)
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, test2FACode)
coVerify { authRepository.getAuthInfoSrp(testSessionId, testUsername) }
assertTrue(result)
@@ -141,11 +140,10 @@ class ObtainPasswordScopeTest {
testUserId,
testSrpProofs,
authInfoResult.srpSession,
null,
null
)
} returns false
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, null, null)
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, null)
coVerify { authRepository.getAuthInfoSrp(testSessionId, testUsername) }
assertFalse(result)
@@ -158,11 +156,10 @@ class ObtainPasswordScopeTest {
testUserId,
testSrpProofs,
authInfoResult.srpSession,
test2FACode,
null
test2FACode
)
} returns false
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, test2FACode, null)
val result = useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, test2FACode)
coVerify { authRepository.getAuthInfoSrp(testSessionId, testUsername) }
assertFalse(result)
@@ -175,7 +172,6 @@ class ObtainPasswordScopeTest {
testUserId,
testSrpProofs,
authInfoResult.srpSession,
null,
null
)
} throws ApiException(
@@ -188,7 +184,7 @@ class ObtainPasswordScopeTest {
// WHEN
val throwable = assertFailsWith(ApiException::class) {
useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, null, null)
useCase.invoke(testUserId, testSessionId, testUsername, testPasswordEncrypted, null)
}
// THEN
+140 -97
View File
@@ -435,7 +435,7 @@ public final class me/proton/core/auth/presentation/alert/TwoFAInputDialog : and
}
public final class me/proton/core/auth/presentation/alert/TwoFAInputDialog$Companion {
public final fun invoke (Ljava/lang/String;Ljava/lang/String;)Lme/proton/core/auth/presentation/alert/TwoFAInputDialog;
public final fun invoke (Lme/proton/core/auth/presentation/viewmodel/Source;Ljava/lang/String;)Lme/proton/core/auth/presentation/alert/TwoFAInputDialog;
}
public abstract interface class me/proton/core/auth/presentation/alert/TwoFAInputDialog_GeneratedInjector {
@@ -1024,14 +1024,14 @@ public final class me/proton/core/auth/presentation/entity/ChooseAddressResult$U
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/ChooseAddressResult$UserCheckError;
}
public final class me/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable : android/os/Parcelable {
public final class me/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/Boolean;
public final fun component3 ()Ljava/lang/Boolean;
public final fun copy (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;
public final fun copy (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getAppId ()Ljava/lang/String;
@@ -1042,22 +1042,22 @@ public final class me/proton/core/auth/presentation/entity/Fido2AuthenticationEx
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable$Creator : android/os/Parcelable$Creator {
public final class me/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;
}
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable : android/os/Parcelable {
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public synthetic fun <init> (Ljava/lang/String;[BLjava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2-TcUX1vc ()[B
public final fun component3 ()Ljava/util/List;
public final fun copy-Coi6ktg (Ljava/lang/String;[BLjava/util/List;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable;
public static synthetic fun copy-Coi6ktg$default (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable;Ljava/lang/String;[BLjava/util/List;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable;
public final fun copy-Coi6ktg (Ljava/lang/String;[BLjava/util/List;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity;
public static synthetic fun copy-Coi6ktg$default (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity;Ljava/lang/String;[BLjava/util/List;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getId-TcUX1vc ()[B
@@ -1068,31 +1068,31 @@ public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredent
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable$Creator : android/os/Parcelable$Creator {
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity;
}
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable : android/os/Parcelable {
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public synthetic fun <init> ([BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> ([BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> ([BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> ([BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-TcUX1vc ()[B
public final fun component2-6VbMDqA ()Lkotlin/ULong;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/util/List;
public final fun component5 ()Ljava/lang/String;
public final fun component6 ()Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;
public final fun copy-ebjZ_cE ([BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;
public static synthetic fun copy-ebjZ_cE$default (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;[BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;
public final fun component6 ()Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;
public final fun copy-ebjZ_cE ([BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;
public static synthetic fun copy-ebjZ_cE$default (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;[BLkotlin/ULong;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getAllowCredentials ()Ljava/util/List;
public final fun getChallenge-TcUX1vc ()[B
public final fun getExtensions ()Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;
public final fun getExtensions ()Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;
public final fun getRpId ()Ljava/lang/String;
public final fun getTimeout-6VbMDqA ()Lkotlin/ULong;
public final fun getUserVerification ()Ljava/lang/String;
@@ -1101,12 +1101,12 @@ public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredent
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable$Creator : android/os/Parcelable$Creator {
public final class me/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;
}
public final class me/proton/core/auth/presentation/entity/LoginInput : android/os/Parcelable {
@@ -1252,16 +1252,6 @@ public final class me/proton/core/auth/presentation/entity/PasswordInput$Creator
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/PasswordInput;
}
public final class me/proton/core/auth/presentation/entity/PasswordInputKt {
public static final fun fromParcelable (Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;)Lme/proton/core/auth/fido/domain/entity/Fido2AuthenticationExtensionsClientInputs;
public static final fun fromParcelable (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable;)Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialDescriptor;
public static final fun fromParcelable (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;)Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialRequestOptions;
public static final fun fromParcelable (Lme/proton/core/auth/presentation/entity/TwoFaFido;)Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;
public static final fun toParcelable (Lme/proton/core/auth/fido/domain/entity/Fido2AuthenticationExtensionsClientInputs;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsParcelable;
public static final fun toParcelable (Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialDescriptor;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorParcelable;
public static final fun toParcelable (Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialRequestOptions;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;
}
public final class me/proton/core/auth/presentation/entity/SecondFactorInput : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lme/proton/core/account/domain/entity/AccountType;Z)V
@@ -1290,6 +1280,88 @@ public final class me/proton/core/auth/presentation/entity/SecondFactorInput$Cre
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/SecondFactorInput;
}
public abstract class me/proton/core/auth/presentation/entity/SecondFactorProofEntity : android/os/Parcelable {
}
public final class me/proton/core/auth/presentation/entity/SecondFactorProofEntity$Fido2Entity : me/proton/core/auth/presentation/entity/SecondFactorProofEntity {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;[B[B[B[B)V
public fun describeContents ()I
public final fun getAuthenticatorData ()[B
public final fun getClientData ()[B
public final fun getCredentialID ()[B
public final fun getPublicKeyOptions ()Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;
public final fun getSignature ()[B
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/SecondFactorProofEntity$Fido2Entity$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$Fido2Entity;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$Fido2Entity;
}
public final class me/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorCodeEntity : me/proton/core/auth/presentation/entity/SecondFactorProofEntity {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorCodeEntity;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorCodeEntity;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorCodeEntity;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getCode ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorCodeEntity$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorCodeEntity;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorCodeEntity;
}
public final class me/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorSignatureEntity : me/proton/core/auth/presentation/entity/SecondFactorProofEntity {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorSignatureEntity;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorSignatureEntity;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorSignatureEntity;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getClientData ()Ljava/lang/String;
public final fun getKeyHandle ()Ljava/lang/String;
public final fun getSignatureData ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorSignatureEntity$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorSignatureEntity;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$SecondFactorSignatureEntity;
}
public final class me/proton/core/auth/presentation/entity/SecondFactorProofEntityKt {
public static final fun fromEntity (Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;)Lme/proton/core/auth/fido/domain/entity/Fido2AuthenticationExtensionsClientInputs;
public static final fun fromEntity (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity;)Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialDescriptor;
public static final fun fromEntity (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;)Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialRequestOptions;
public static final fun fromEntity (Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity$Fido2Entity;)Lme/proton/core/auth/fido/domain/entity/SecondFactorProof$Fido2;
public static final fun fromEntity (Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity;)Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;
public static final fun toEntity (Lme/proton/core/auth/fido/domain/entity/Fido2AuthenticationExtensionsClientInputs;)Lme/proton/core/auth/presentation/entity/Fido2AuthenticationExtensionsClientInputsEntity;
public static final fun toEntity (Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialDescriptor;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialDescriptorEntity;
public static final fun toEntity (Lme/proton/core/auth/fido/domain/entity/Fido2PublicKeyCredentialRequestOptions;)Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsEntity;
}
public abstract class me/proton/core/auth/presentation/entity/SecondFactorResult : android/os/Parcelable {
}
@@ -1389,32 +1461,6 @@ public final class me/proton/core/auth/presentation/entity/SessionResult$Creator
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/SessionResult;
}
public final class me/proton/core/auth/presentation/entity/TwoFAInput : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> ()V
public fun <init> (Ljava/lang/String;Lme/proton/core/auth/presentation/entity/TwoFaFido;)V
public synthetic fun <init> (Ljava/lang/String;Lme/proton/core/auth/presentation/entity/TwoFaFido;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Lme/proton/core/auth/presentation/entity/TwoFaFido;
public final fun copy (Ljava/lang/String;Lme/proton/core/auth/presentation/entity/TwoFaFido;)Lme/proton/core/auth/presentation/entity/TwoFAInput;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/TwoFAInput;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/TwoFaFido;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/TwoFAInput;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getTwoFA ()Ljava/lang/String;
public final fun getTwoFAFido ()Lme/proton/core/auth/presentation/entity/TwoFaFido;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/TwoFAInput$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/TwoFAInput;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/TwoFAInput;
}
public final class me/proton/core/auth/presentation/entity/TwoFAMechanisms : java/lang/Enum {
public static final field Companion Lme/proton/core/auth/presentation/entity/TwoFAMechanisms$Companion;
public static final field ONE_TIME_CODE Lme/proton/core/auth/presentation/entity/TwoFAMechanisms;
@@ -1430,36 +1476,6 @@ public final class me/proton/core/auth/presentation/entity/TwoFAMechanisms$Compa
public final fun getMap ()Ljava/util/Map;
}
public final class me/proton/core/auth/presentation/entity/TwoFaFido : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;[B[B[B[B)V
public final fun component1 ()Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;
public final fun component2 ()[B
public final fun component3 ()[B
public final fun component4 ()[B
public final fun component5 ()[B
public final fun copy (Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;[B[B[B[B)Lme/proton/core/auth/presentation/entity/TwoFaFido;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/TwoFaFido;Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;[B[B[B[BILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/TwoFaFido;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getAuthenticatorData ()[B
public final fun getClientData ()[B
public final fun getCredentialID ()[B
public final fun getPublicKeyOptions ()Lme/proton/core/auth/presentation/entity/Fido2PublicKeyCredentialRequestOptionsParcelable;
public final fun getSignature ()[B
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/TwoFaFido$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/TwoFaFido;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/TwoFaFido;
}
public final class me/proton/core/auth/presentation/entity/TwoPassModeInput : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Lme/proton/core/account/domain/entity/AccountType;)V
@@ -2627,8 +2643,8 @@ public final class me/proton/core/auth/presentation/viewmodel/ConfirmPasswordDia
public fun onResultEnqueueObservability (Lme/proton/core/util/kotlin/coroutine/ResultCollector;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun onSignResult (Lme/proton/core/auth/fido/domain/usecase/PerformTwoFaWithSecurityKey$Result;)V
public final fun setFido2Info (Lme/proton/core/auth/domain/entity/Fido2Info;)V
public final fun unlock (Lme/proton/core/domain/entity/UserId;Lme/proton/core/network/domain/scopes/Scope;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;)Lkotlinx/coroutines/Job;
public static synthetic fun unlock$default (Lme/proton/core/auth/presentation/viewmodel/ConfirmPasswordDialogViewModel;Lme/proton/core/domain/entity/UserId;Lme/proton/core/network/domain/scopes/Scope;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
public final fun unlock (Lme/proton/core/domain/entity/UserId;Lme/proton/core/network/domain/scopes/Scope;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)Lkotlinx/coroutines/Job;
public static synthetic fun unlock$default (Lme/proton/core/auth/presentation/viewmodel/ConfirmPasswordDialogViewModel;Lme/proton/core/domain/entity/UserId;Lme/proton/core/network/domain/scopes/Scope;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
}
public abstract class me/proton/core/auth/presentation/viewmodel/ConfirmPasswordDialogViewModel$State {
@@ -2894,7 +2910,7 @@ public final class me/proton/core/auth/presentation/viewmodel/SecondFactorViewMo
public fun onResultEnqueueObservability (Lme/proton/core/util/kotlin/coroutine/ResultCollector;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun setup (Lme/proton/core/domain/entity/UserId;)Lkotlinx/coroutines/Job;
public final fun startSecondFactorFlow (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/account/domain/entity/AccountType;ZLjava/lang/String;)Lkotlinx/coroutines/Job;
public final fun startSecondFactorFlow (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/account/domain/entity/AccountType;ZLme/proton/core/auth/domain/entity/SecondFactorProof;)Lkotlinx/coroutines/Job;
public final fun startSecondFactorFlow (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/account/domain/entity/AccountType;ZLme/proton/core/auth/fido/domain/entity/SecondFactorProof;)Lkotlinx/coroutines/Job;
public final fun stopSecondFactorFlow (Lme/proton/core/domain/entity/UserId;)Lkotlinx/coroutines/Job;
}
@@ -2982,14 +2998,24 @@ public final class me/proton/core/auth/presentation/viewmodel/SecondFactorViewMo
public static fun provide ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/Source : java/lang/Enum {
public static final field changePassword Lme/proton/core/auth/presentation/viewmodel/Source;
public static final field changeRecoveryEmail Lme/proton/core/auth/presentation/viewmodel/Source;
public final class me/proton/core/auth/presentation/viewmodel/Source : java/lang/Enum, android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public static final field ChangePassword Lme/proton/core/auth/presentation/viewmodel/Source;
public static final field ChangeRecoveryEmail Lme/proton/core/auth/presentation/viewmodel/Source;
public fun describeContents ()I
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public final fun getValue ()Ljava/lang/String;
public final fun toScreenId ()Lme/proton/core/observability/domain/metrics/ChangePasswordOrRecoveryEmailFidoLaunchResultTotal$ScreenId;
public final fun toScreenId ()Lme/proton/core/observability/domain/metrics/common/TwoFaDialogScreenId;
public static fun valueOf (Ljava/lang/String;)Lme/proton/core/auth/presentation/viewmodel/Source;
public static fun values ()[Lme/proton/core/auth/presentation/viewmodel/Source;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/viewmodel/Source$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/viewmodel/Source;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/viewmodel/Source;
}
public final class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel : me/proton/core/presentation/viewmodel/ProtonViewModel, me/proton/core/observability/domain/ObservabilityContext {
@@ -3015,6 +3041,16 @@ public abstract class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialo
public final class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Error$InvalidAccount : me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Error {
public static final field INSTANCE Lme/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Error$InvalidAccount;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Error$SetupError : me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Error {
public static final field INSTANCE Lme/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Error$SetupError;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Idle : me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State {
@@ -3028,6 +3064,13 @@ public final class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogVi
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Loading : me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State {
public static final field INSTANCE Lme/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel$State$Loading;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel_Factory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/auth/presentation/viewmodel/TwoFAInputDialogViewModel_Factory;
+1 -1
View File
@@ -31,7 +31,7 @@ protonBuild {
}
protonCoverage {
branchCoveragePercentage.set(43)
branchCoveragePercentage.set(42)
lineCoveragePercentage.set(60)
}
@@ -65,7 +65,7 @@ fun FragmentManager.showTwoFAEnterDialog(
userId: UserId
) {
findFragmentByTag(TAG_TWO_FA_ENTER_DIALOG) ?: run {
val fragment = TwoFAInputDialog(source.value, userId.id)
val fragment = TwoFAInputDialog(source, userId.id)
if (largeLayout) {
// For large screens (tablets), we show the fragment as a dialog
fragment.show(this, TAG_TWO_FA_ENTER_DIALOG)
@@ -40,14 +40,13 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.auth.fido.domain.usecase.PerformTwoFaWithSecurityKey
import me.proton.core.auth.presentation.LogTag
import me.proton.core.auth.presentation.databinding.Dialog2faInputBinding
import me.proton.core.auth.presentation.entity.TwoFAInput
import me.proton.core.auth.presentation.entity.SecondFactorProofEntity
import me.proton.core.auth.presentation.entity.TwoFAMechanisms
import me.proton.core.auth.presentation.entity.TwoFaFido
import me.proton.core.auth.presentation.entity.toParcelable
import me.proton.core.auth.presentation.entity.toEntity
import me.proton.core.auth.presentation.util.setTextWithAnnotatedLink
import me.proton.core.auth.presentation.viewmodel.Source
import me.proton.core.auth.presentation.viewmodel.TwoFAInputDialogViewModel
@@ -55,6 +54,7 @@ import me.proton.core.domain.entity.UserId
import me.proton.core.presentation.R
import me.proton.core.presentation.utils.ProtectScreenConfiguration
import me.proton.core.presentation.utils.ScreenContentProtector
import me.proton.core.presentation.utils.SnackbarLength
import me.proton.core.presentation.utils.errorSnack
import me.proton.core.presentation.utils.errorToast
import me.proton.core.presentation.utils.onClick
@@ -78,7 +78,7 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
const val KEY_2FA_SET = "key.2fa_set"
const val BUNDLE_KEY_2FA_DATA = "bundle.2fa_data"
operator fun invoke(source: String, userId: String) = TwoFAInputDialog().apply {
operator fun invoke(source: Source, userId: String) = TwoFAInputDialog().apply {
arguments = bundleOf(
ARG_SOURCE to source,
ARG_USER_ID to userId
@@ -93,11 +93,14 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
}
private val source by lazy {
Source.valueOf(requireNotNull(requireArguments().getString(ARG_SOURCE)))
requireArguments().let {
it.classLoader = Source::class.java.classLoader
requireNotNull(it.getParcelable<Source>(ARG_SOURCE))
}
}
private val binding by lazy {
Dialog2faInputBinding.inflate(LayoutInflater.from(requireContext()))
Dialog2faInputBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -111,36 +114,57 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
binding.tabLayout.addOnTabSelectedListener(this@TwoFAInputDialog)
val builder = MaterialAlertDialogBuilder(requireContext())
val alertDialog = MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.presentation_authenticate)
// passing null to the listeners is a workaround to prevent the dialog to auto-dismiss on button click
.setPositiveButton(R.string.presentation_alert_enter, null)
.setNegativeButton(R.string.presentation_alert_cancel, null)
.setView(binding.root)
val alertDialog = builder.create()
.create()
viewModel.state
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.distinctUntilChanged()
.onEach {
when (it) {
is TwoFAInputDialogViewModel.State.Idle -> with(binding) {
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = true
progressLayout.isVisible = false
tabLayout.isVisible = it.showSecurityKey
if (it.showSecurityKey) {
selectSecurityKeyTab()
} else {
selectOneTimeCodeTab()
}
}
is TwoFAInputDialogViewModel.State.Loading -> {
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false
binding.oneTimeCodeGroup.isVisible = false
binding.securityKeyGroup.isVisible = false
binding.tabLayout.isVisible = false
binding.progressLayout.isVisible = true
}
is TwoFAInputDialogViewModel.State.Error.InvalidAccount -> {
requireContext().errorToast(getString(R.string.presentation_error_general))
dismissAllowingStateLoss()
}
is TwoFAInputDialogViewModel.State.Error.SetupError -> binding.root.errorSnack(
R.string.presentation_error_general,
length = SnackbarLength.INDEFINITE
) {
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false
binding.progressLayout.isVisible = false
setAction(R.string.presentation_retry) {
viewModel.setup(userId)
}
}
}
}.launchIn(lifecycleScope)
return alertDialog.apply {
viewModel.state
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.distinctUntilChanged()
.onEach {
when (it) {
is TwoFAInputDialogViewModel.State.Idle -> with(binding){
progressLayout.isVisible = false
it.showSecurityKey
tabLayout.isVisible = it.showSecurityKey
if (it.showSecurityKey) {
selectSecurityKeyTab()
} else {
selectOneTimeCodeTab()
}
}
is TwoFAInputDialogViewModel.State.Error.InvalidAccount ->
requireContext().errorToast(getString(R.string.presentation_error_general))
}
}.launchIn(lifecycleScope)
setOnShowListener {
viewModel.setup(userId)
@@ -148,19 +172,9 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
getButton(AlertDialog.BUTTON_POSITIVE).apply {
isAllCaps = false
onClick {
with(binding) {
when (selectedTwoFAOption()) {
TwoFAMechanisms.SECURITY_KEY -> onSecurityKeySubmitted()
TwoFAMechanisms.ONE_TIME_CODE -> {
parentFragmentManager.setFragmentResult(
KEY_2FA_SET, bundleOf(
BUNDLE_KEY_2FA_DATA to TwoFAInput(twoFA.text.toString())
)
)
dismissAllowingStateLoss()
}
}
when (selectedTwoFAOption()) {
TwoFAMechanisms.SECURITY_KEY -> onSecurityKeySubmitted()
TwoFAMechanisms.ONE_TIME_CODE -> onOneTimeCodeSubmitted()
}
}
}
@@ -189,9 +203,9 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
}
}
override fun onTabUnselected(p0: TabLayout.Tab?) { }
override fun onTabUnselected(p0: TabLayout.Tab?) = Unit
override fun onTabReselected(p0: TabLayout.Tab?) { }
override fun onTabReselected(p0: TabLayout.Tab?) = Unit
private fun onTwoFaWithSecurityKeyResult(
result: PerformTwoFaWithSecurityKey.Result,
@@ -200,7 +214,7 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
viewModel.onSignResult(source, result)
when (result) {
is PerformTwoFaWithSecurityKey.Result.Success -> {
val secondFactorFido = SecondFactorFido(
val secondFactorFido = SecondFactorProof.Fido2(
publicKeyOptions = options,
clientData = result.response.clientDataJSON,
authenticatorData = result.response.authenticatorData,
@@ -210,16 +224,17 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
parentFragmentManager.setFragmentResult(
KEY_2FA_SET, bundleOf(
BUNDLE_KEY_2FA_DATA to TwoFAInput(twoFAFido = TwoFaFido(
secondFactorFido.publicKeyOptions.toParcelable(),
BUNDLE_KEY_2FA_DATA to SecondFactorProofEntity.Fido2Entity(
secondFactorFido.publicKeyOptions.toEntity(),
secondFactorFido.clientData,
secondFactorFido.authenticatorData,
secondFactorFido.signature,
secondFactorFido.credentialID
))
)
)
)
}
is PerformTwoFaWithSecurityKey.Result.Cancelled -> Unit
is PerformTwoFaWithSecurityKey.Result.EmptyResult -> binding.root.errorSnack(
getString(me.proton.core.auth.presentation.R.string.auth_login_general_error)
@@ -236,16 +251,19 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
}
}
private fun selectSecurityKeyTab() = with (binding) {
private fun selectSecurityKeyTab() = with(binding) {
oneTimeCodeGroup.isVisible = false
securityKeyGroup.isVisible = true
securityKeyText.setTextWithAnnotatedLink(me.proton.core.auth.presentation.R.string.auth_2fa_insert_security_key, "more") {
securityKeyText.setTextWithAnnotatedLink(
me.proton.core.auth.presentation.R.string.auth_2fa_insert_security_key,
"more"
) {
context?.openBrowserLink(getString(me.proton.core.auth.presentation.R.string.confirm_password_2fa_security_key))
}
}
private fun selectOneTimeCodeTab() = with (binding) {
private fun selectOneTimeCodeTab() = with(binding) {
oneTimeCodeGroup.isVisible = true
securityKeyGroup.isVisible = false
}
@@ -253,8 +271,16 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
private fun selectedTwoFAOption(): TwoFAMechanisms =
if (binding.tabLayout.isVisible) {
TwoFAMechanisms.enumOf(binding.tabLayout.selectedTabPosition)
}
else TwoFAMechanisms.ONE_TIME_CODE
} else TwoFAMechanisms.ONE_TIME_CODE
private fun onOneTimeCodeSubmitted() {
parentFragmentManager.setFragmentResult(
KEY_2FA_SET, bundleOf(
BUNDLE_KEY_2FA_DATA to SecondFactorProofEntity.SecondFactorCodeEntity(binding.twoFA.text.toString())
)
)
dismissAllowingStateLoss()
}
private fun onSecurityKeySubmitted() {
val performTwoFaWithSecurityKey = performTwoFaWithSecurityKey.getOrNull() ?: return
@@ -271,8 +297,7 @@ class TwoFAInputDialog : DialogFragment(), TabLayout.OnTabSelectedListener {
)
}
is PerformTwoFaWithSecurityKey.LaunchResult.Success,
null -> Unit
is PerformTwoFaWithSecurityKey.LaunchResult.Success -> Unit
}
}
}
@@ -37,7 +37,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import me.proton.core.auth.domain.entity.SecondFactorMethod
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.auth.fido.domain.usecase.PerformTwoFaWithSecurityKey
import me.proton.core.auth.presentation.LogTag
import me.proton.core.auth.presentation.R
@@ -155,8 +155,8 @@ class ConfirmPasswordDialog : DialogFragment() {
private fun onTotpSubmitted() {
val password = viewController.password.orEmpty()
val twoFactorCode = viewController.twoFactorCode
viewModel.unlock(userId, missingScope, password, secondFactorCode = twoFactorCode)
val twoFactorCode = viewController.twoFactorCode.orEmpty()
viewModel.unlock(userId, missingScope, password, secondFactorProof = SecondFactorProof.SecondFactorCode(twoFactorCode))
}
private fun onSecurityKeySubmitted() {
@@ -256,7 +256,7 @@ class ConfirmPasswordDialog : DialogFragment() {
userId = userId,
missingScope = missingScope,
password = password,
secondFactorFido = SecondFactorFido(
secondFactorProof = SecondFactorProof.Fido2(
publicKeyOptions = options,
clientData = result.response.clientDataJSON,
authenticatorData = result.response.authenticatorData,
@@ -20,110 +20,9 @@ package me.proton.core.auth.presentation.entity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import me.proton.core.auth.fido.domain.entity.Fido2AuthenticationExtensionsClientInputs
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialDescriptor
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
@Parcelize
data class PasswordInput(
val password: String
): Parcelable
@Parcelize
data class TwoFAInput(
val twoFA: String? = null,
val twoFAFido: TwoFaFido? = null
): Parcelable
@Parcelize
data class TwoFaFido(
val publicKeyOptions: Fido2PublicKeyCredentialRequestOptionsParcelable,
val clientData: ByteArray,
val authenticatorData: ByteArray,
val signature: ByteArray,
val credentialID: ByteArray
): Parcelable
@Parcelize
data class Fido2PublicKeyCredentialRequestOptionsParcelable(
val challenge: UByteArray,
val timeout: ULong? = null, // milliseconds
val rpId: String? = null,
val allowCredentials: List<Fido2PublicKeyCredentialDescriptorParcelable>? = null,
val userVerification: String? = null,
val extensions: Fido2AuthenticationExtensionsClientInputsParcelable? = null
): Parcelable
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialRequestOptionsParcelable.fromParcelable() =
Fido2PublicKeyCredentialRequestOptions(
challenge = challenge,
timeout = timeout,
rpId = rpId,
allowCredentials = allowCredentials?.map { it.fromParcelable() },
userVerification = userVerification,
extensions = extensions?.fromParcelable()
)
@OptIn(ExperimentalUnsignedTypes::class)
@Parcelize
data class Fido2PublicKeyCredentialDescriptorParcelable(
val type: String,
val id: UByteArray,
val transports: List<String>?
): Parcelable
@Parcelize
data class Fido2AuthenticationExtensionsClientInputsParcelable(
val appId: String?,
val thirdPartyPayment: Boolean?,
val uvm: Boolean?,
): Parcelable
fun TwoFaFido.fromParcelable() =
SecondFactorFido(
publicKeyOptions = publicKeyOptions.fromParcelable(),
clientData = clientData,
authenticatorData = authenticatorData,
signature = signature,
credentialID = credentialID
)
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialDescriptorParcelable.fromParcelable() =
Fido2PublicKeyCredentialDescriptor(
type = type,
id = id,
transports = transports
)
fun Fido2AuthenticationExtensionsClientInputsParcelable.fromParcelable() =
Fido2AuthenticationExtensionsClientInputs(
appId = appId,
thirdPartyPayment = thirdPartyPayment,
uvm = uvm
)
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialRequestOptions.toParcelable() = Fido2PublicKeyCredentialRequestOptionsParcelable(
challenge = challenge,
timeout = timeout,
rpId = rpId,
allowCredentials = allowCredentials?.map { it.toParcelable() },
userVerification = userVerification,
extensions = extensions?.toParcelable()
)
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialDescriptor.toParcelable() = Fido2PublicKeyCredentialDescriptorParcelable(
type = type,
id = id,
transports = transports
)
fun Fido2AuthenticationExtensionsClientInputs.toParcelable() = Fido2AuthenticationExtensionsClientInputsParcelable(
appId = appId,
thirdPartyPayment = thirdPartyPayment,
uvm = uvm
)
@@ -0,0 +1,140 @@
/*
* Copyright (c) 2020 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.auth.presentation.entity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import me.proton.core.auth.fido.domain.entity.Fido2AuthenticationExtensionsClientInputs
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialDescriptor
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
sealed class SecondFactorProofEntity : Parcelable {
@Parcelize
data class SecondFactorCodeEntity(
val code: String
) : SecondFactorProofEntity()
@Parcelize
data class SecondFactorSignatureEntity(
val keyHandle: String,
val clientData: String,
val signatureData: String
) : SecondFactorProofEntity()
@Parcelize
class Fido2Entity(
val publicKeyOptions: Fido2PublicKeyCredentialRequestOptionsEntity,
val clientData: ByteArray,
val authenticatorData: ByteArray,
val signature: ByteArray,
val credentialID: ByteArray
) : SecondFactorProofEntity()
}
@Parcelize
data class Fido2PublicKeyCredentialRequestOptionsEntity(
val challenge: UByteArray,
val timeout: ULong? = null, // milliseconds
val rpId: String? = null,
val allowCredentials: List<Fido2PublicKeyCredentialDescriptorEntity>? = null,
val userVerification: String? = null,
val extensions: Fido2AuthenticationExtensionsClientInputsEntity? = null
): Parcelable
@OptIn(ExperimentalUnsignedTypes::class)
@Parcelize
data class Fido2PublicKeyCredentialDescriptorEntity(
val type: String,
val id: UByteArray,
val transports: List<String>?
): Parcelable
@Parcelize
data class Fido2AuthenticationExtensionsClientInputsEntity(
val appId: String?,
val thirdPartyPayment: Boolean?,
val uvm: Boolean?,
): Parcelable
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialRequestOptionsEntity.fromEntity() =
Fido2PublicKeyCredentialRequestOptions(
challenge = challenge,
timeout = timeout,
rpId = rpId,
allowCredentials = allowCredentials?.map { it.fromEntity() },
userVerification = userVerification,
extensions = extensions?.fromEntity()
)
fun SecondFactorProofEntity.fromEntity() =
when (this) {
is SecondFactorProofEntity.SecondFactorCodeEntity -> SecondFactorProof.SecondFactorCode(code)
is SecondFactorProofEntity.SecondFactorSignatureEntity -> SecondFactorProof.SecondFactorSignature(keyHandle, clientData, signatureData)
is SecondFactorProofEntity.Fido2Entity -> fromEntity()
}
fun SecondFactorProofEntity.Fido2Entity.fromEntity() =
SecondFactorProof.Fido2(
publicKeyOptions = publicKeyOptions.fromEntity(),
clientData = clientData,
authenticatorData = authenticatorData,
signature = signature,
credentialID = credentialID
)
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialDescriptorEntity.fromEntity() =
Fido2PublicKeyCredentialDescriptor(
type = type,
id = id,
transports = transports
)
fun Fido2AuthenticationExtensionsClientInputsEntity.fromEntity() =
Fido2AuthenticationExtensionsClientInputs(
appId = appId,
thirdPartyPayment = thirdPartyPayment,
uvm = uvm
)
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialRequestOptions.toEntity() = Fido2PublicKeyCredentialRequestOptionsEntity(
challenge = challenge,
timeout = timeout,
rpId = rpId,
allowCredentials = allowCredentials?.map { it.toEntity() },
userVerification = userVerification,
extensions = extensions?.toEntity()
)
@OptIn(ExperimentalUnsignedTypes::class)
fun Fido2PublicKeyCredentialDescriptor.toEntity() = Fido2PublicKeyCredentialDescriptorEntity(
type = type,
id = id,
transports = transports
)
fun Fido2AuthenticationExtensionsClientInputs.toEntity() = Fido2AuthenticationExtensionsClientInputsEntity(
appId = appId,
thirdPartyPayment = thirdPartyPayment,
uvm = uvm
)
@@ -34,10 +34,10 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.usecase.PostLoginAccountSetup
import me.proton.core.auth.fido.domain.entity.Fido2AuthenticationOptions
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.auth.fido.domain.usecase.PerformTwoFaWithSecurityKey
import me.proton.core.auth.presentation.LogTag
import me.proton.core.auth.presentation.R
@@ -39,9 +39,9 @@ import me.proton.core.auth.domain.feature.IsFido2Enabled
import me.proton.core.auth.domain.usecase.GetAuthInfoSrp
import me.proton.core.auth.domain.usecase.scopes.ObtainLockedScope
import me.proton.core.auth.domain.usecase.scopes.ObtainPasswordScope
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.auth.fido.domain.usecase.PerformTwoFaWithSecurityKey
import me.proton.core.auth.fido.domain.usecase.toStatus
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.keystore.encrypt
import me.proton.core.domain.entity.UserId
@@ -120,15 +120,10 @@ class ConfirmPasswordDialogViewModel @Inject constructor(
userId: UserId,
missingScope: Scope,
password: String,
secondFactorCode: String? = null,
secondFactorFido: SecondFactorFido? = null
secondFactorProof: SecondFactorProof? = null
) = flowWithResultContext {
check(secondFactorCode == null || secondFactorFido == null) {
"Cannot unlock ${missingScope.value} scope using both 2FA code and security key."
}
it.onResultEnqueueObservability("unlockUserForPasswordScope") {
toConfirmPasswordSubmissionTotal(secondFactorCode, secondFactorFido)
toConfirmPasswordSubmissionTotal(secondFactorProof)
}
send(State.ProcessingObtainScope)
@@ -145,8 +140,7 @@ class ConfirmPasswordDialogViewModel @Inject constructor(
sessionId = requireNotNull(account.sessionId),
username = requireNotNull(account.username),
password = password.encrypt(keyStoreCrypto),
secondFactorCode = secondFactorCode?.takeIfNotEmpty(),
secondFactorFido = secondFactorFido
secondFactorProof = secondFactorProof
)
Scope.LOCKED -> obtainLockedScope(
@@ -185,12 +179,11 @@ class ConfirmPasswordDialogViewModel @Inject constructor(
}
private fun Result<*>.toConfirmPasswordSubmissionTotal(
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): ConfirmPasswordSubmissionTotal {
val secondFactorProofType = when {
secondFactorCode != null -> SecondFactorProofType.totp
secondFactorFido != null -> SecondFactorProofType.securityKey
secondFactorProof is SecondFactorProof.SecondFactorCode -> SecondFactorProofType.totp
secondFactorProof is SecondFactorProof.Fido2 -> SecondFactorProofType.securityKey
else -> SecondFactorProofType.none
}
return if (exceptionOrNull() is InvalidServerAuthenticationException) {
@@ -32,13 +32,13 @@ import kotlinx.coroutines.launch
import me.proton.core.account.domain.entity.AccountType
import me.proton.core.accountmanager.domain.AccountManager
import me.proton.core.accountmanager.domain.AccountWorkflowHandler
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.entity.fido2AuthenticationOptions
import me.proton.core.auth.domain.feature.IsFido2Enabled
import me.proton.core.auth.domain.usecase.PerformSecondFactor
import me.proton.core.auth.domain.usecase.PostLoginAccountSetup
import me.proton.core.auth.domain.usecase.primaryKeyExists
import me.proton.core.auth.fido.domain.entity.Fido2AuthenticationOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.auth.fido.domain.usecase.PerformTwoFaWithSecurityKey
import me.proton.core.auth.fido.domain.usecase.toStatus
import me.proton.core.auth.presentation.LogTag
@@ -18,6 +18,7 @@
package me.proton.core.auth.presentation.viewmodel
import android.os.Parcelable
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -27,6 +28,7 @@ import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.parcelize.Parcelize
import me.proton.core.accountmanager.domain.AccountManager
import me.proton.core.auth.domain.entity.Fido2Info
import me.proton.core.auth.domain.entity.SecondFactor
@@ -61,13 +63,16 @@ class TwoFAInputDialogViewModel @Inject constructor(
sealed class State {
data class Idle(val showSecurityKey: Boolean) : State()
data object Loading: State()
sealed class Error : State() {
object InvalidAccount : Error()
data object InvalidAccount : Error()
data object SetupError : Error()
}
}
fun setup(userId: UserId) = flow {
emit(State.Loading)
when {
!isFido2Enabled(userId) -> emit(State.Idle(false))
else -> {
@@ -86,7 +91,7 @@ class TwoFAInputDialogViewModel @Inject constructor(
}
}
}.catch { _ ->
emit(State.Idle(false))
emit(State.Error.SetupError)
}.onEach { state ->
_state.tryEmit(state)
}.launchIn(viewModelScope)
@@ -100,13 +105,14 @@ class TwoFAInputDialogViewModel @Inject constructor(
}
}
enum class Source(val value: String) {
changePassword("changePassword"),
changeRecoveryEmail("changeRecoveryEmail");
@Parcelize
enum class Source: Parcelable {
ChangePassword,
ChangeRecoveryEmail;
fun toScreenId() = when (this) {
changePassword -> TwoFaDialogScreenId.changePassword
changeRecoveryEmail -> TwoFaDialogScreenId.changeRecoveryEmail
ChangePassword -> TwoFaDialogScreenId.changePassword
ChangeRecoveryEmail -> TwoFaDialogScreenId.changeRecoveryEmail
}
}
@@ -97,13 +97,9 @@
<FrameLayout
android:id="@+id/progressLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:windowBackground"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:elevation="3dp"
tools:visibility="gone">
@@ -36,6 +36,7 @@ import me.proton.core.auth.domain.feature.IsFido2Enabled
import me.proton.core.auth.domain.usecase.GetAuthInfoSrp
import me.proton.core.auth.domain.usecase.scopes.ObtainLockedScope
import me.proton.core.auth.domain.usecase.scopes.ObtainPasswordScope
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.domain.entity.UserId
import me.proton.core.network.domain.ApiException
@@ -79,7 +80,7 @@ class ConfirmPasswordDialogViewModelTest :
private val testUsername = "test-username"
private val testPassword = "test-password"
private val testPasswordEncrypted = "test-password-encrypted"
private val test2FACode = "test-2fa"
private val test2FACode = SecondFactorProof.SecondFactorCode("test-2fa")
private val testUserId = UserId(testUserIdString)
private val testSessionId = SessionId("test-sessionId")
@@ -200,7 +201,6 @@ class ConfirmPasswordDialogViewModelTest :
testSessionId,
testUsername,
testPasswordEncrypted,
null,
null
)
} returns true
@@ -226,7 +226,6 @@ class ConfirmPasswordDialogViewModelTest :
testSessionId,
testUsername,
testPasswordEncrypted,
null,
null
)
} throws ApiException(
@@ -260,8 +259,7 @@ class ConfirmPasswordDialogViewModelTest :
testSessionId,
testUsername,
testPasswordEncrypted,
test2FACode,
null
test2FACode
)
} returns true
flowTest(viewModel.state) {
@@ -286,8 +284,7 @@ class ConfirmPasswordDialogViewModelTest :
testSessionId,
testUsername,
testPasswordEncrypted,
test2FACode,
null
test2FACode
)
} throws ApiException(
ApiResult.Error.Http(
@@ -29,10 +29,10 @@ import me.proton.core.account.domain.entity.AccountType
import me.proton.core.accountmanager.domain.AccountManager
import me.proton.core.accountmanager.domain.AccountWorkflowHandler
import me.proton.core.auth.domain.entity.ScopeInfo
import me.proton.core.auth.domain.entity.SecondFactorProof
import me.proton.core.auth.domain.feature.IsFido2Enabled
import me.proton.core.auth.domain.usecase.PerformSecondFactor
import me.proton.core.auth.domain.usecase.PostLoginAccountSetup
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.auth.presentation.entity.SessionResult
import me.proton.core.domain.entity.UserId
import me.proton.core.network.domain.session.SessionId
+1 -1
View File
@@ -1175,7 +1175,7 @@ public final class me/proton/core/key/data/repository/PrivateKeyRepositoryImpl :
public fun createAddressKey (Lme/proton/core/domain/entity/UserId;Lme/proton/core/key/domain/entity/key/PrivateAddressKey;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun reactivatePrivateKey (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/key/domain/entity/key/PrivateKey;Ljava/util/List;Ljava/util/Map;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun setupInitialKeys (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updatePrivateKeys (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updatePrivateKeys (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/proton/core/key/data/repository/PublicAddressRepositoryImpl : me/proton/core/key/domain/repository/PublicAddressRepository {
@@ -18,10 +18,11 @@
package me.proton.core.key.data.repository
import me.proton.core.auth.data.api.request.toFido2Request
import me.proton.core.auth.data.api.request.toSecondFactorCode
import me.proton.core.auth.data.api.request.toSecondFactorFido
import me.proton.core.auth.data.api.response.isSuccess
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.pgp.Armored
import me.proton.core.crypto.common.srp.Auth
import me.proton.core.crypto.common.srp.SrpProofs
@@ -102,8 +103,7 @@ class PrivateKeyRepositoryImpl @Inject constructor(
keySalt: String,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
auth: Auth?,
keys: List<Key>?,
userKeys: List<Key>?
@@ -115,8 +115,8 @@ class PrivateKeyRepositoryImpl @Inject constructor(
clientEphemeral = srpProofs.clientEphemeral,
clientProof = srpProofs.clientProof,
srpSession = srpSession,
twoFactorCode = secondFactorCode,
fido2 = secondFactorFido?.toFido2Request(),
twoFactorCode = secondFactorProof.toSecondFactorCode(),
fido2 = secondFactorProof.toSecondFactorFido(),
auth = if (auth != null) AuthRequest.from(auth) else null,
keys = keys?.map {
PrivateKeyRequest(privateKey = it.privateKey, id = it.keyId.id)
@@ -26,6 +26,7 @@ import kotlinx.coroutines.test.runTest
import me.proton.core.auth.data.api.response.SRPAuthenticationResponse
import me.proton.core.auth.domain.exception.InvalidServerAuthenticationException
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.EncryptedByteArray
import me.proton.core.crypto.common.srp.Auth
import me.proton.core.crypto.common.srp.SrpProofs
@@ -106,8 +107,7 @@ class PrivateKeyRepositoryImplTest {
keySalt = "test-key-salt",
srpProofs = testSrpProofs,
srpSession = "test-srp-session",
secondFactorCode = "test-2fa-code",
secondFactorFido = null,
secondFactorProof = SecondFactorProof.SecondFactorCode("test-2fa-code"),
auth = mockk(relaxed = true),
keys = listOf(mockk(relaxed = true)),
userKeys = listOf(mockk(relaxed = true))
+2 -2
View File
@@ -714,11 +714,11 @@ public abstract interface class me/proton/core/key/domain/repository/PrivateKeyR
public abstract fun createAddressKey (Lme/proton/core/domain/entity/UserId;Lme/proton/core/key/domain/entity/key/PrivateAddressKey;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun reactivatePrivateKey (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/key/domain/entity/key/PrivateKey;Ljava/util/List;Ljava/util/Map;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun setupInitialKeys (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updatePrivateKeys (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updatePrivateKeys (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/proton/core/key/domain/repository/PrivateKeyRepository$DefaultImpls {
public static synthetic fun updatePrivateKeys$default (Lme/proton/core/key/domain/repository/PrivateKeyRepository;Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static synthetic fun updatePrivateKeys$default (Lme/proton/core/key/domain/repository/PrivateKeyRepository;Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
}
public abstract interface class me/proton/core/key/domain/repository/PublicAddressRepository {
@@ -18,7 +18,7 @@
package me.proton.core.key.domain.repository
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.pgp.Armored
import me.proton.core.crypto.common.srp.Auth
import me.proton.core.crypto.common.srp.SrpProofs
@@ -56,8 +56,7 @@ interface PrivateKeyRepository {
keySalt: String,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
auth: Auth?,
keys: List<Key>? = null,
userKeys: List<Key>? = null
@@ -70,8 +70,8 @@ public final class me/proton/core/usersettings/data/api/UserSettingsRemoteDataSo
public fun fetch (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun setRecoverySecret (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun setUsername (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateUserSettings (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/domain/entity/UserSettingsProperty;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
@@ -973,8 +973,8 @@ public final class me/proton/core/usersettings/data/repository/UserSettingsRepos
public fun markAsStale (Lme/proton/core/domain/entity/UserId;)V
public fun setUsername (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateCrashReports (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateTelemetry (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateUserSettings (Lme/proton/core/usersettings/domain/entity/UserSettings;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
@@ -18,9 +18,10 @@
package me.proton.core.usersettings.data.api
import me.proton.core.auth.data.api.request.toFido2Request
import me.proton.core.auth.data.api.request.toSecondFactorCode
import me.proton.core.auth.data.api.request.toSecondFactorFido
import me.proton.core.auth.domain.entity.ServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.pgp.Based64Encoded
import me.proton.core.crypto.common.pgp.EncryptedSignature
import me.proton.core.crypto.common.srp.Auth
@@ -82,16 +83,15 @@ class UserSettingsRemoteDataSourceImpl @Inject constructor(
email: String,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): Pair<UserSettings, ServerProof> =
result("updateRecoveryEmail") {
apiProvider.get<UserSettingsApi>(sessionUserId).invoke {
updateRecoveryEmail(
UpdateRecoveryEmailRequest(
email = email,
twoFactorCode = secondFactorCode,
fido2 = secondFactorFido?.toFido2Request(),
twoFactorCode = secondFactorProof.toSecondFactorCode(),
fido2 = secondFactorProof.toSecondFactorFido(),
clientEphemeral = srpProofs.clientEphemeral,
clientProof = srpProofs.clientProof,
srpSession = srpSession
@@ -106,16 +106,15 @@ class UserSettingsRemoteDataSourceImpl @Inject constructor(
sessionUserId: SessionUserId,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
auth: Auth
): Pair<UserSettings, ServerProof> =
result("updateLoginPassword") {
apiProvider.get<UserSettingsApi>(sessionUserId).invoke {
updateLoginPassword(
UpdateLoginPasswordRequest(
twoFactorCode = secondFactorCode,
fido2 = secondFactorFido?.toFido2Request(),
twoFactorCode = secondFactorProof.toSecondFactorCode(),
fido2 = secondFactorProof.toSecondFactorFido(),
clientEphemeral = srpProofs.clientEphemeral,
clientProof = srpProofs.clientProof,
srpSession = srpSession,
@@ -27,7 +27,7 @@ import com.dropbox.android.external.store4.StoreRequest
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.srp.Auth
import me.proton.core.crypto.common.srp.SrpProofs
import me.proton.core.data.arch.buildProtonStore
@@ -87,16 +87,14 @@ class UserSettingsRepositoryImpl @Inject constructor(
email: String,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?,
): UserSettings {
val (userSettings, serverProof) = remoteDataSource.updateRecoveryEmail(
sessionUserId = sessionUserId,
email = email,
srpProofs = srpProofs,
srpSession = srpSession,
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido
secondFactorProof = secondFactorProof
)
validateServerProof(serverProof, srpProofs.expectedServerProof) { "recovery email update failed" }
localDataSource.insertOrUpdate(userSettings)
@@ -107,16 +105,14 @@ class UserSettingsRepositoryImpl @Inject constructor(
sessionUserId: SessionUserId,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
auth: Auth
): UserSettings {
val (userSettings, serverProof) = remoteDataSource.updateLoginPassword(
sessionUserId = sessionUserId,
srpProofs = srpProofs,
srpSession = srpSession,
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido,
secondFactorProof = secondFactorProof,
auth = auth
)
validateServerProof(serverProof, srpProofs.expectedServerProof) { "password change failed" }
@@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import me.proton.core.auth.domain.exception.InvalidServerAuthenticationException
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.srp.Auth
import me.proton.core.crypto.common.srp.SrpProofs
import me.proton.core.domain.entity.UserId
@@ -157,8 +158,7 @@ class UserSettingsRepositoryImplTest {
email = "test-email2",
srpProofs = testSrpProofs,
srpSession = "test-srp-session",
secondFactorCode = "",
secondFactorFido = null
secondFactorProof = SecondFactorProof.SecondFactorCode("")
)
// THEN
assertNotNull(response)
@@ -179,8 +179,7 @@ class UserSettingsRepositoryImplTest {
email = "test-email2",
srpProofs = testSrpProofs,
srpSession = "test-srp-session",
secondFactorCode = "",
secondFactorFido = null
secondFactorProof = SecondFactorProof.SecondFactorCode("")
)
}
assertEquals(
@@ -222,8 +221,7 @@ class UserSettingsRepositoryImplTest {
sessionUserId = UserId(testUserId),
srpProofs = testSrpProofs,
srpSession = "test-srp-session",
secondFactorCode = "",
secondFactorFido = null,
secondFactorProof = SecondFactorProof.SecondFactorCode(""),
auth = testAuth
)
// THEN
@@ -244,8 +242,7 @@ class UserSettingsRepositoryImplTest {
sessionUserId = UserId(testUserId),
srpProofs = testSrpProofs,
srpSession = "test-srp-session",
secondFactorCode = "",
secondFactorFido = null,
secondFactorProof = SecondFactorProof.SecondFactorCode(""),
auth = testAuth
)
}
@@ -347,8 +347,8 @@ public abstract interface class me/proton/core/usersettings/domain/repository/Us
public abstract fun fetch (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun setRecoverySecret (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun setUsername (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateUserSettings (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/domain/entity/UserSettingsProperty;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
@@ -358,8 +358,8 @@ public abstract interface class me/proton/core/usersettings/domain/repository/Us
public abstract fun markAsStale (Lme/proton/core/domain/entity/UserId;)V
public abstract fun setUsername (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateCrashReports (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateLoginPassword (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateTelemetry (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateUserSettings (Lme/proton/core/usersettings/domain/entity/UserSettings;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
@@ -415,12 +415,12 @@ public final class me/proton/core/usersettings/domain/usecase/PerformUpdateCrash
public final class me/proton/core/usersettings/domain/usecase/PerformUpdateLoginPassword {
public fun <init> (Lme/proton/core/crypto/common/context/CryptoContext;Lme/proton/core/account/domain/repository/AccountRepository;Lme/proton/core/auth/domain/repository/AuthRepository;Lme/proton/core/user/domain/repository/UserRepository;Lme/proton/core/usersettings/domain/repository/UserSettingsRepository;)V
public final fun invoke (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun invoke (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/proton/core/usersettings/domain/usecase/PerformUpdateRecoveryEmail {
public fun <init> (Lme/proton/core/account/domain/repository/AccountRepository;Lme/proton/core/auth/domain/repository/AuthRepository;Lme/proton/core/user/domain/repository/UserRepository;Lme/proton/core/usersettings/domain/repository/UserSettingsRepository;Lme/proton/core/crypto/common/srp/SrpCrypto;Lme/proton/core/crypto/common/keystore/KeyStoreCrypto;)V
public final fun invoke (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun invoke (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/proton/core/usersettings/domain/usecase/PerformUpdateTelemetry {
@@ -430,7 +430,7 @@ public final class me/proton/core/usersettings/domain/usecase/PerformUpdateTelem
public final class me/proton/core/usersettings/domain/usecase/PerformUpdateUserPassword {
public fun <init> (Lme/proton/core/crypto/common/context/CryptoContext;Lme/proton/core/account/domain/repository/AccountRepository;Lme/proton/core/auth/domain/repository/AuthRepository;Lme/proton/core/user/domain/UserManager;Lme/proton/core/user/domain/repository/UserRepository;)V
public final fun invoke (ZLme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun invoke (ZLme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/proton/core/usersettings/domain/usecase/SetupUsername {
@@ -19,7 +19,7 @@
package me.proton.core.usersettings.domain.repository
import me.proton.core.auth.domain.entity.ServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.pgp.Based64Encoded
import me.proton.core.crypto.common.pgp.EncryptedSignature
import me.proton.core.crypto.common.srp.Auth
@@ -39,16 +39,14 @@ interface UserSettingsRemoteDataSource {
email: String,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): Pair<UserSettings, ServerProof>
suspend fun updateLoginPassword(
sessionUserId: SessionUserId,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
auth: Auth
): Pair<UserSettings, ServerProof>
@@ -19,7 +19,7 @@
package me.proton.core.usersettings.domain.repository
import kotlinx.coroutines.flow.Flow
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.srp.Auth
import me.proton.core.crypto.common.srp.SrpProofs
import me.proton.core.domain.arch.DataResult
@@ -69,8 +69,7 @@ interface UserSettingsRepository {
email: String,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): UserSettings
/**
@@ -80,8 +79,7 @@ interface UserSettingsRepository {
sessionUserId: SessionUserId,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
auth: Auth
): UserSettings
@@ -20,7 +20,7 @@ package me.proton.core.usersettings.domain.usecase
import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.keystore.decrypt
@@ -47,8 +47,7 @@ class PerformUpdateLoginPassword @Inject constructor(
userId: UserId,
password: EncryptedString,
newPassword: EncryptedString,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): UserSettings {
val user = userRepository.getUser(userId)
val username = user.nameNotNull()
@@ -76,8 +75,7 @@ class PerformUpdateLoginPassword @Inject constructor(
sessionUserId = userId,
srpProofs = clientProofs,
srpSession = loginInfo.srpSession,
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido,
secondFactorProof = secondFactorProof,
auth = auth
)
}
@@ -20,7 +20,7 @@ package me.proton.core.usersettings.domain.usecase
import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.keystore.decrypt
@@ -46,8 +46,7 @@ class PerformUpdateRecoveryEmail @Inject constructor(
sessionUserId: SessionUserId,
newRecoveryEmail: String,
password: EncryptedString,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): UserSettings {
val user = userRepository.getUser(sessionUserId)
val username = user.nameNotNull()
@@ -67,8 +66,7 @@ class PerformUpdateRecoveryEmail @Inject constructor(
email = newRecoveryEmail,
srpProofs = clientProofs,
srpSession = loginInfo.srpSession,
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido
secondFactorProof = secondFactorProof
)
}
}
@@ -20,7 +20,7 @@ package me.proton.core.usersettings.domain.usecase
import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.keystore.decrypt
@@ -49,8 +49,7 @@ class PerformUpdateUserPassword @Inject constructor(
userId: UserId,
loginPassword: EncryptedString,
newPassword: EncryptedString,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): Boolean {
val user = userRepository.getUser(userId)
val username = user.nameNotNull()
@@ -84,8 +83,7 @@ class PerformUpdateUserPassword @Inject constructor(
return userManager.changePassword(
userId = userId,
newPassword = newPassword,
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido,
secondFactorProof = secondFactorProof,
proofs = clientProofs,
srpSession = loginInfo.srpSession,
auth = auth
@@ -22,14 +22,12 @@ import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import kotlinx.coroutines.test.runTest
import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.auth.domain.entity.AuthInfo
import me.proton.core.auth.domain.entity.Modulus
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.srp.Auth
@@ -63,7 +61,7 @@ class PerformUpdateLoginPasswordTest {
private val testUserId = UserId("test-user-id")
private val testUsername = "test-username"
private val testPassword = "test-password"
private val testSecondFactor = "123456"
private val testSecondFactor = SecondFactorProof.SecondFactorCode("123456")
private val testSrpSession = "test-srp-session"
private val testModulus = "test-modulus"
private val testServerEphemeral = "test-server-ephemeral"
@@ -140,8 +138,7 @@ class PerformUpdateLoginPasswordTest {
sessionUserId = testUserId,
srpProofs = any(),
srpSession = any(),
secondFactorCode = testSecondFactor,
secondFactorFido = null,
secondFactorProof = testSecondFactor,
auth = testAuth
)
} returns testUserSettingsResponse
@@ -194,8 +191,7 @@ class PerformUpdateLoginPasswordTest {
userId = testUserId,
password = keyStoreCrypto.encrypt(testPassword),
newPassword = keyStoreCrypto.encrypt(testNewPassword),
secondFactorCode = testSecondFactor,
secondFactorFido = null
secondFactorProof = testSecondFactor,
)
// THEN
coVerify(exactly = 1) {
@@ -203,8 +199,7 @@ class PerformUpdateLoginPasswordTest {
sessionUserId = testUserId,
srpProofs = any(),
srpSession = any(),
secondFactorCode = testSecondFactor,
secondFactorFido = null,
secondFactorProof = testSecondFactor,
auth = testAuth
)
}
@@ -214,15 +209,14 @@ class PerformUpdateLoginPasswordTest {
@Test
fun `update login password with fido2 returns success`() = runTest {
// GIVEN
val testSecondFactorFido = mockk<SecondFactorFido>(relaxed = true)
val testSecondFactorFido = mockk<SecondFactorProof.Fido2>(relaxed = true)
// WHEN
val result = useCase.invoke(
userId = testUserId,
password = keyStoreCrypto.encrypt(testPassword),
newPassword = keyStoreCrypto.encrypt(testNewPassword),
secondFactorCode = null,
secondFactorFido = testSecondFactorFido
secondFactorProof = testSecondFactorFido
)
// THEN
coVerify(exactly = 1) {
@@ -230,8 +224,7 @@ class PerformUpdateLoginPasswordTest {
sessionUserId = testUserId,
srpProofs = any(),
srpSession = any(),
secondFactorCode = null,
secondFactorFido = testSecondFactorFido,
secondFactorProof = testSecondFactorFido,
auth = testAuth
)
}
@@ -26,6 +26,7 @@ import kotlinx.coroutines.test.runTest
import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.auth.domain.entity.AuthInfo
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.srp.SrpCrypto
import me.proton.core.domain.entity.UserId
@@ -55,7 +56,7 @@ class PerformUpdateRecoveryEmailTest {
private val testUserId = UserId("test-user-id")
private val testUsername = "test-username"
private val testPassword = "test-password"
private val testSecondFactor = "123456"
private val testSecondFactor = SecondFactorProof.SecondFactorCode("123456")
private val testSrpSession = "test-srp-session"
private val testModulus = "test-modulus"
private val testServerEphemeral = "test-server-ephemeral"
@@ -105,7 +106,6 @@ class PerformUpdateRecoveryEmailTest {
any(),
any(),
any(),
any(),
any()
)
} returns testUserSettingsResponse
@@ -144,8 +144,7 @@ class PerformUpdateRecoveryEmailTest {
sessionUserId = testUserId,
newRecoveryEmail = "",
password = keyStoreCrypto.encrypt(testPassword),
secondFactorCode = testSecondFactor,
secondFactorFido = null
secondFactorProof = testSecondFactor
)
coVerify(exactly = 1) {
userSettingsRepository.updateRecoveryEmail(
@@ -153,8 +152,7 @@ class PerformUpdateRecoveryEmailTest {
email = "",
srpProofs = any(),
srpSession = any(),
secondFactorCode = testSecondFactor,
secondFactorFido = null
secondFactorProof = testSecondFactor
)
}
assertNotNull(result)
@@ -189,8 +187,7 @@ class PerformUpdateRecoveryEmailTest {
sessionUserId = testUserId,
newRecoveryEmail = "",
password = testPassword,
secondFactorCode = testSecondFactor,
secondFactorFido = null
secondFactorProof = testSecondFactor
)
coVerify(exactly = 1) {
userSettingsRepository.updateRecoveryEmail(
@@ -198,8 +195,7 @@ class PerformUpdateRecoveryEmailTest {
email = "",
srpProofs = any(),
srpSession = any(),
secondFactorCode = testSecondFactor,
secondFactorFido = null
secondFactorProof = testSecondFactor
)
}
assertNotNull(result)
@@ -26,7 +26,7 @@ import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.auth.domain.entity.AuthInfo
import me.proton.core.auth.domain.entity.Modulus
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.pgp.PGPCrypto
@@ -58,7 +58,7 @@ class PerformUpdateUserPasswordTest {
private val testSessionId = SessionId("test-session-id")
private val testUserId = UserId("test-user-id")
private val testUsername = "test-username"
private val testSecondFactor = "123456"
private val testSecondFactorCode = SecondFactorProof.SecondFactorCode("123456")
private val testKeySalt = "test-keysalt"
private val testSrpSession = "test-srp-session"
private val testLoginPassword = "test-login-password"
@@ -118,8 +118,7 @@ class PerformUpdateUserPasswordTest {
userManager.changePassword(
userId = testUserId,
newPassword = any(),
secondFactorCode = any(),
secondFactorFido = null,
secondFactorProof = any(),
proofs = any(),
srpSession = any(),
auth = any()
@@ -180,8 +179,7 @@ class PerformUpdateUserPasswordTest {
assertFailsWith(IllegalArgumentException::class) {
useCase.invoke(
userId = testUserId,
secondFactorCode = testSecondFactor,
secondFactorFido = null,
secondFactorProof = testSecondFactorCode,
loginPassword = keyStoreCrypto.encrypt(testLoginPassword),
newPassword = keyStoreCrypto.encrypt(testNewMailboxPassword),
twoPasswordMode = false
@@ -192,14 +190,13 @@ class PerformUpdateUserPasswordTest {
@Test
fun `update mailbox password fido2`() = runTest {
coEvery { userRepository.getUser(testUserId) } returns testUser
val secondFactorFido = mockk<SecondFactorFido>(relaxed = true)
val secondFactorFido = mockk<SecondFactorProof.Fido2>(relaxed = true)
coEvery {
userManager.changePassword(
userId = testUserId,
newPassword = any(),
secondFactorCode = null,
secondFactorFido = secondFactorFido,
secondFactorProof = secondFactorFido,
proofs = any(),
srpSession = any(),
auth = any()
@@ -208,8 +205,7 @@ class PerformUpdateUserPasswordTest {
val result = useCase.invoke(
userId = testUserId,
secondFactorCode = null,
secondFactorFido = secondFactorFido,
secondFactorProof = secondFactorFido,
loginPassword = keyStoreCrypto.encrypt(testLoginPassword),
newPassword = keyStoreCrypto.encrypt(testNewMailboxPassword),
twoPasswordMode = false
@@ -171,17 +171,16 @@ public final class me/proton/core/usersettings/presentation/entity/SettingsInput
public final class me/proton/core/usersettings/presentation/entity/TwoFaDialogArguments : android/os/Parcelable {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Lme/proton/core/auth/presentation/viewmodel/Source;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lme/proton/core/usersettings/presentation/entity/TwoFaDialogArguments;
public static synthetic fun copy$default (Lme/proton/core/usersettings/presentation/entity/TwoFaDialogArguments;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/usersettings/presentation/entity/TwoFaDialogArguments;
public final fun component2 ()Lme/proton/core/auth/presentation/viewmodel/Source;
public final fun copy (Ljava/lang/String;Lme/proton/core/auth/presentation/viewmodel/Source;)Lme/proton/core/usersettings/presentation/entity/TwoFaDialogArguments;
public static synthetic fun copy$default (Lme/proton/core/usersettings/presentation/entity/TwoFaDialogArguments;Ljava/lang/String;Lme/proton/core/auth/presentation/viewmodel/Source;ILjava/lang/Object;)Lme/proton/core/usersettings/presentation/entity/TwoFaDialogArguments;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getSource ()Lme/proton/core/auth/presentation/viewmodel/Source;
public final fun getSourceString ()Ljava/lang/String;
public final fun getUser ()Lme/proton/core/domain/entity/UserId;
public final fun getUserId ()Ljava/lang/String;
public final fun getUserId ()Lme/proton/core/domain/entity/UserId;
public final fun getUserIdString ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
@@ -350,7 +349,7 @@ public final class me/proton/core/usersettings/presentation/ui/StartTwoFAInputDi
public synthetic fun createIntent (Landroid/content/Context;Ljava/lang/Object;)Landroid/content/Intent;
public fun createIntent (Landroid/content/Context;Lme/proton/core/usersettings/presentation/entity/TwoFaDialogArguments;)Landroid/content/Intent;
public synthetic fun parseResult (ILandroid/content/Intent;)Ljava/lang/Object;
public fun parseResult (ILandroid/content/Intent;)Lme/proton/core/auth/presentation/entity/TwoFAInput;
public fun parseResult (ILandroid/content/Intent;)Lme/proton/core/auth/presentation/entity/SecondFactorProofEntity;
}
public final class me/proton/core/usersettings/presentation/ui/StartUpdateRecoveryEmail : androidx/activity/result/contract/ActivityResultContract {
@@ -455,15 +454,13 @@ public final class me/proton/core/usersettings/presentation/viewmodel/PasswordMa
public final class me/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$SetTwoFactor : me/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action {
public static final field $stable I
public fun <init> (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;)V
public fun <init> (Lme/proton/core/domain/entity/UserId;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)V
public final fun component1 ()Lme/proton/core/domain/entity/UserId;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;
public final fun copy (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$SetTwoFactor;
public static synthetic fun copy$default (Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$SetTwoFactor;Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;ILjava/lang/Object;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$SetTwoFactor;
public final fun component2 ()Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;
public final fun copy (Lme/proton/core/domain/entity/UserId;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$SetTwoFactor;
public static synthetic fun copy$default (Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$SetTwoFactor;Lme/proton/core/domain/entity/UserId;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;ILjava/lang/Object;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$SetTwoFactor;
public fun equals (Ljava/lang/Object;)Z
public final fun getCode ()Ljava/lang/String;
public final fun getTwoFAFido ()Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;
public final fun getSecondFactorProof ()Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;
public fun getUserId ()Lme/proton/core/domain/entity/UserId;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
@@ -471,21 +468,19 @@ public final class me/proton/core/usersettings/presentation/viewmodel/PasswordMa
public final class me/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$UpdatePassword : me/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action {
public static final field $stable I
public fun <init> (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;)V
public synthetic fun <init> (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)V
public synthetic fun <init> (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Lme/proton/core/domain/entity/UserId;
public final fun component2 ()Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/String;
public final fun component5 ()Ljava/lang/String;
public final fun component6 ()Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;
public final fun copy (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$UpdatePassword;
public static synthetic fun copy$default (Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$UpdatePassword;Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;ILjava/lang/Object;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$UpdatePassword;
public final fun component5 ()Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;
public final fun copy (Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$UpdatePassword;
public static synthetic fun copy$default (Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$UpdatePassword;Lme/proton/core/domain/entity/UserId;Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;ILjava/lang/Object;)Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$Action$UpdatePassword;
public fun equals (Ljava/lang/Object;)Z
public final fun getNewPassword ()Ljava/lang/String;
public final fun getPassword ()Ljava/lang/String;
public final fun getSecondFactorCode ()Ljava/lang/String;
public final fun getSecondFactorFido ()Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;
public final fun getSecondFactorProof ()Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;
public final fun getType ()Lme/proton/core/usersettings/presentation/viewmodel/PasswordManagementViewModel$PasswordType;
public fun getUserId ()Lme/proton/core/domain/entity/UserId;
public fun hashCode ()I
@@ -610,7 +605,7 @@ public final class me/proton/core/usersettings/presentation/viewmodel/UpdateReco
public final fun getState ()Lkotlinx/coroutines/flow/StateFlow;
public final fun setNewRecoveryEmail (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;)V
public final fun setPassword (Ljava/lang/String;)V
public final fun setSecondFactor (Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;)V
public final fun setSecondFactor (Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;)V
}
public abstract class me/proton/core/usersettings/presentation/viewmodel/UpdateRecoveryEmailViewModel$State {
+1 -1
View File
@@ -31,7 +31,7 @@ protonBuild {
protonCoverage {
branchCoveragePercentage.set(42)
lineCoveragePercentage.set(53)
lineCoveragePercentage.set(55)
}
publishOption.shouldBePublishedAsLib = true
@@ -26,11 +26,9 @@ import me.proton.core.domain.entity.UserId
@Parcelize
data class TwoFaDialogArguments(
val userId: String,
val sourceString: String
val userIdString: String,
val source: Source
) : Parcelable {
@IgnoredOnParcel
val user = UserId(userId)
@IgnoredOnParcel
val source = Source.valueOf(sourceString)
}
val userId = UserId(userIdString)
}
@@ -22,7 +22,7 @@ import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.activity.result.contract.ActivityResultContract
import me.proton.core.auth.presentation.entity.TwoFAInput
import me.proton.core.auth.presentation.entity.SecondFactorProofEntity
import me.proton.core.usersettings.presentation.entity.SettingsInput
import me.proton.core.usersettings.presentation.entity.PasswordManagementResult
import me.proton.core.usersettings.presentation.entity.TwoFaDialogArguments
@@ -53,14 +53,14 @@ class StartPasswordManagement : ActivityResultContract<SettingsInput, PasswordMa
}
}
class StartTwoFAInputDialog : ActivityResultContract<TwoFaDialogArguments, TwoFAInput?>() {
class StartTwoFAInputDialog : ActivityResultContract<TwoFaDialogArguments, SecondFactorProofEntity?>() {
override fun createIntent(context: Context, input: TwoFaDialogArguments): Intent =
Intent(context, TwoFaInputActivity::class.java).apply {
putExtra(TwoFaInputActivity.ARG_INPUT, input)
}
override fun parseResult(resultCode: Int, intent: Intent?): TwoFAInput? {
override fun parseResult(resultCode: Int, intent: Intent?): SecondFactorProofEntity? {
if (resultCode != Activity.RESULT_OK) return null
return intent?.getParcelableExtra(TwoFaInputActivity.ARG_RESULT)
}
@@ -39,7 +39,7 @@ import me.proton.core.accountrecovery.presentation.compose.ui.AccountRecoveryDia
import me.proton.core.accountrecovery.presentation.compose.ui.PasswordResetDialogActivity
import me.proton.core.accountrecovery.presentation.compose.view.AccountRecoveryInfo
import me.proton.core.auth.domain.IsCommonPasswordCheckEnabled
import me.proton.core.auth.presentation.entity.fromParcelable
import me.proton.core.auth.presentation.entity.fromEntity
import me.proton.core.auth.presentation.viewmodel.Source
import me.proton.core.compose.theme.ProtonTheme
import me.proton.core.domain.entity.UserId
@@ -86,7 +86,7 @@ class PasswordManagementFragment :
private val twoFactorLauncher = registerForActivityResult(StartTwoFAInputDialog()) { result ->
if (result != null) {
viewModel.perform(Action.SetTwoFactor(userId, result.twoFA, result.twoFAFido?.fromParcelable()))
viewModel.perform(Action.SetTwoFactor(userId, result.fromEntity()))
} else {
viewModel.perform(Action.CancelTwoFactor(userId))
}
@@ -175,7 +175,7 @@ class PasswordManagementFragment :
}
is PasswordManagementViewModel.State.TwoFactorNeeded -> {
twoFactorLauncher.launch(TwoFaDialogArguments(userId.id, Source.changePassword.value))
twoFactorLauncher.launch(TwoFaDialogArguments(userId.id, Source.ChangePassword))
}
is PasswordManagementViewModel.State.Success -> {
@@ -26,7 +26,7 @@ import me.proton.core.auth.presentation.alert.TwoFAInputDialog
import me.proton.core.auth.presentation.alert.showPasswordEnterDialog
import me.proton.core.auth.presentation.alert.showTwoFAEnterDialog
import me.proton.core.auth.presentation.entity.PasswordInput
import me.proton.core.auth.presentation.entity.TwoFAInput
import me.proton.core.auth.presentation.entity.SecondFactorProofEntity
import me.proton.core.auth.presentation.viewmodel.Source
import me.proton.core.domain.entity.UserId
import me.proton.core.presentation.ui.alert.FragmentDialogResultLauncher
@@ -61,7 +61,7 @@ fun FragmentManager.registerShowTwoFADialogResultLauncher(
context: ComponentActivity,
source: Source,
userId: UserId,
onResult: (TwoFAInput?) -> Unit
onResult: (SecondFactorProofEntity?) -> Unit
): FragmentDialogResultLauncher<Unit> {
setFragmentResultListener(
@@ -69,7 +69,7 @@ fun FragmentManager.registerShowTwoFADialogResultLauncher(
context
) { _, bundle ->
val result =
bundle.getParcelable<TwoFAInput>(TwoFAInputDialog.BUNDLE_KEY_2FA_DATA)
bundle.getParcelable<SecondFactorProofEntity>(TwoFAInputDialog.BUNDLE_KEY_2FA_DATA)
onResult(result)
}
@@ -22,8 +22,6 @@ import android.app.Activity
import android.content.Intent
import android.os.Bundle
import dagger.hilt.android.AndroidEntryPoint
import me.proton.core.auth.presentation.viewmodel.Source
import me.proton.core.domain.entity.UserId
import me.proton.core.presentation.ui.ProtonActivity
import me.proton.core.usersettings.presentation.entity.TwoFaDialogArguments
@@ -39,7 +37,7 @@ class TwoFaInputActivity : ProtonActivity() {
}
private val userId by lazy {
twoFaDialogArguments.user
twoFaDialogArguments.userId
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -28,7 +28,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import me.proton.core.auth.presentation.entity.fromParcelable
import me.proton.core.auth.presentation.entity.fromEntity
import me.proton.core.auth.presentation.viewmodel.Source
import me.proton.core.domain.entity.UserId
import me.proton.core.presentation.ui.ProtonFragment
@@ -59,7 +59,7 @@ class UpdateRecoveryEmailFragment : ProtonFragment(R.layout.fragment_update_reco
private lateinit var showPasswordDialogResultLauncher: FragmentDialogResultLauncher<Unit>
private val showTwoFADialogResultLauncher = registerForActivityResult(StartTwoFAInputDialog()) { result ->
if (result != null) {
viewModel.setSecondFactor(result.twoFA, result.twoFAFido?.fromParcelable())
viewModel.setSecondFactor(result.fromEntity())
}
}
@@ -113,7 +113,9 @@ class UpdateRecoveryEmailFragment : ProtonFragment(R.layout.fragment_update_reco
showPasswordDialogResultLauncher.show(Unit)
}
is UpdateRecoveryEmailViewModel.State.SecondFactorNeeded -> {
showTwoFADialogResultLauncher.launch(TwoFaDialogArguments(userId.id, Source.changeRecoveryEmail.value))
showTwoFADialogResultLauncher.launch(
TwoFaDialogArguments(userId.id, Source.ChangeRecoveryEmail)
)
}
}.exhaustive
}.launchIn(viewLifecycleOwner.lifecycleScope)
@@ -34,7 +34,7 @@ import kotlinx.coroutines.flow.stateIn
import me.proton.core.accountrecovery.domain.IsAccountRecoveryResetEnabled
import me.proton.core.accountrecovery.domain.usecase.ObserveUserRecovery
import me.proton.core.accountrecovery.domain.usecase.ObserveUserRecoverySelfInitiated
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.compose.viewmodel.stopTimeoutMillis
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.keystore.encrypt
@@ -135,8 +135,7 @@ class PasswordManagementViewModel @Inject constructor(
userId = action.userId,
password = encryptedPassword,
newPassword = encryptedNewPassword,
secondFactorCode = action.secondFactorCode,
secondFactorFido = action.secondFactorFido
secondFactorProof = action.secondFactorProof
)
emit(State.Success)
}
@@ -150,8 +149,7 @@ class PasswordManagementViewModel @Inject constructor(
userId = action.userId,
loginPassword = encryptedLoginPassword,
newPassword = encryptedNewMailboxPassword,
secondFactorCode = action.secondFactorCode,
secondFactorFido = action.secondFactorFido
secondFactorProof = action.secondFactorProof
)
emit(State.Success)
}
@@ -165,8 +163,7 @@ class PasswordManagementViewModel @Inject constructor(
userId = action.userId,
loginPassword = encryptedLoginPassword,
newPassword = encryptedNewMailboxPassword,
secondFactorCode = action.secondFactorCode,
secondFactorFido = action.secondFactorFido
secondFactorProof = action.secondFactorProof
)
emit(State.Success)
}
@@ -184,7 +181,7 @@ class PasswordManagementViewModel @Inject constructor(
}
private suspend fun setTwoFactor(action: Action.SetTwoFactor): Flow<State> {
val passwordAction = requireNotNull(pendingUpdate?.copy(secondFactorCode = action.code, secondFactorFido = action.twoFAFido))
val passwordAction = requireNotNull(pendingUpdate?.copy(secondFactorProof = action.secondFactorProof))
return updatePassword(passwordAction)
}
@@ -258,14 +255,12 @@ class PasswordManagementViewModel @Inject constructor(
val type: PasswordType,
val password: String,
val newPassword: String,
val secondFactorCode: String? = "",
val secondFactorFido: SecondFactorFido? = null
val secondFactorProof: SecondFactorProof? = null
) : Action(userId)
data class SetTwoFactor(
override val userId: UserId,
val code: String?,
val twoFAFido: SecondFactorFido?
val secondFactorProof: SecondFactorProof?
) : Action(userId)
data class CancelTwoFactor(
@@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.crypto.common.keystore.encrypt
@@ -83,8 +83,8 @@ class UpdateRecoveryEmailViewModel @Inject constructor(
}
}
fun setSecondFactor(secondFactorCode: String?, secondFactorFido: SecondFactorFido?) {
updateRecoveryEmail(secondFactorCode, secondFactorFido)
fun setSecondFactor(secondFactorProof: SecondFactorProof?) {
updateRecoveryEmail(secondFactorProof)
}
/**
@@ -106,16 +106,14 @@ class UpdateRecoveryEmailViewModel @Inject constructor(
* Updates (replaces) the user's recovery email address.
*/
private fun updateRecoveryEmail(
secondFactorCode: String? = null,
secondFactorFido: SecondFactorFido? = null
secondFactorProof: SecondFactorProof? = null
) = flow {
emit(State.UpdatingCurrent)
val updateRecoveryEmailResult = performUpdateRecoveryEmail(
sessionUserId = checkNotNull(userId),
newRecoveryEmail = checkNotNull(recoveryEmail),
password = checkNotNull(inputPassword),
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido
secondFactorProof = secondFactorProof
)
emit(State.UpdatingSuccess(updateRecoveryEmailResult.email?.value))
}.catch { error ->
@@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.flowOf
import me.proton.core.accountrecovery.domain.IsAccountRecoveryResetEnabled
import me.proton.core.accountrecovery.domain.usecase.ObserveUserRecovery
import me.proton.core.accountrecovery.domain.usecase.ObserveUserRecoverySelfInitiated
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.domain.entity.Product
import me.proton.core.domain.entity.UserId
@@ -190,7 +191,7 @@ class PasswordManagementViewModelTest : ArchTest by ArchTest(), CoroutinesTest b
)
)
coEvery { performUpdateMailboxPassword.invoke(any(), testUserId, any(), any(), any(), any()) } returns true
coEvery { performUpdateMailboxPassword.invoke(any(), testUserId, any(), any(), any()) } returns true
flowTest(viewModel.state) {
// WHEN
@@ -210,8 +211,7 @@ class PasswordManagementViewModelTest : ArchTest by ArchTest(), CoroutinesTest b
userId = testUserId,
loginPassword = "encrypted-test-password",
newPassword = "encrypted-test-new-password",
secondFactorCode = "",
secondFactorFido = null,
secondFactorProof = null,
twoPasswordMode = false
)
}
@@ -235,7 +235,7 @@ class PasswordManagementViewModelTest : ArchTest by ArchTest(), CoroutinesTest b
)
)
coEvery { performUpdateMailboxPassword.invoke(any(), any(), any(), any(), any(), any()) } returns true
coEvery { performUpdateMailboxPassword.invoke(any(), any(), any(), any(), any()) } returns true
flowTest(viewModel.state) {
// WHEN
@@ -255,8 +255,7 @@ class PasswordManagementViewModelTest : ArchTest by ArchTest(), CoroutinesTest b
userId = testUserId,
loginPassword = "encrypted-test-password",
newPassword = "encrypted-test-new-password",
secondFactorCode = "",
secondFactorFido = null,
secondFactorProof = null,
twoPasswordMode = true
)
}
@@ -280,7 +279,7 @@ class PasswordManagementViewModelTest : ArchTest by ArchTest(), CoroutinesTest b
)
)
coEvery { performUpdateMailboxPassword.invoke(any(), any(), any(), any(), any(), any()) } returns true
coEvery { performUpdateMailboxPassword.invoke(any(), any(), any(), any(), any()) } returns true
flowTest(viewModel.state) {
// WHEN
@@ -300,8 +299,7 @@ class PasswordManagementViewModelTest : ArchTest by ArchTest(), CoroutinesTest b
userId = testUserId,
loginPassword = "encrypted-test-password",
newPassword = "encrypted-test-new-password",
secondFactorCode = "",
secondFactorFido = null,
secondFactorProof = null,
twoPasswordMode = false
)
}
@@ -21,6 +21,7 @@ package me.proton.core.usersettings.presentation.viewmodel
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.domain.entity.UserId
@@ -145,8 +146,7 @@ class UpdateRecoveryEmailViewModelTest : ArchTest by ArchTest(), CoroutinesTest
sessionUserId = testUserId,
newRecoveryEmail = "",
password = "encrypted-test-password",
secondFactorCode = null,
secondFactorFido = null
secondFactorProof = null
)
} returns testUserSettingsResponse.copy(email = RecoverySetting("", 1, notify = true, reset = true))
@@ -174,8 +174,7 @@ class UpdateRecoveryEmailViewModelTest : ArchTest by ArchTest(), CoroutinesTest
sessionUserId = testUserId,
newRecoveryEmail = "new-email",
password = "encrypted-test-password",
secondFactorCode = null,
secondFactorFido = null
secondFactorProof = null
)
} returns testUserSettingsResponse.copy(email = RecoverySetting("new-email", 1, notify = true, reset = true))
@@ -203,8 +202,7 @@ class UpdateRecoveryEmailViewModelTest : ArchTest by ArchTest(), CoroutinesTest
sessionUserId = testUserId,
newRecoveryEmail = "new-email",
password = "encrypted-test-password",
secondFactorCode = "123456",
secondFactorFido = null
secondFactorProof = SecondFactorProof.SecondFactorCode("123456")
)
} returns testUserSettingsResponse.copy(
email = RecoverySetting("new-email", 1, notify = true, reset = true)
@@ -233,7 +231,7 @@ class UpdateRecoveryEmailViewModelTest : ArchTest by ArchTest(), CoroutinesTest
assertIs<UpdateRecoveryEmailViewModel.State.PasswordNeeded>(awaitItem())
viewModel.setPassword(testPassword)
assertIs<UpdateRecoveryEmailViewModel.State.SecondFactorNeeded>(awaitItem())
viewModel.setSecondFactor("123456", null)
viewModel.setSecondFactor(SecondFactorProof.SecondFactorCode("123456"))
assertIs<UpdateRecoveryEmailViewModel.State.UpdatingCurrent>(awaitItem())
val result = awaitItem()
assertTrue(result is UpdateRecoveryEmailViewModel.State.UpdatingSuccess)
@@ -248,8 +246,7 @@ class UpdateRecoveryEmailViewModelTest : ArchTest by ArchTest(), CoroutinesTest
sessionUserId = testUserId,
newRecoveryEmail = "new-email",
password = "encrypted-test-password",
secondFactorCode = null,
secondFactorFido = null
secondFactorProof = null
)
} throws ApiException(
ApiResult.Error.Http(
+2 -2
View File
@@ -189,7 +189,7 @@ public final class me/proton/core/user/data/UserEvents$Companion {
public final class me/proton/core/user/data/UserManagerImpl : me/proton/core/user/domain/UserManager {
public fun <init> (Lme/proton/core/user/domain/repository/UserRepository;Lme/proton/core/user/domain/repository/UserAddressRepository;Lme/proton/core/user/domain/repository/PassphraseRepository;Lme/proton/core/key/domain/repository/KeySaltRepository;Lme/proton/core/key/domain/repository/PrivateKeyRepository;Lme/proton/core/accountrecovery/domain/repository/AccountRecoveryRepository;Lme/proton/core/user/data/UserAddressKeySecretProvider;Lme/proton/core/crypto/common/context/CryptoContext;Lme/proton/core/user/data/usecase/GenerateSignedKeyList;Ljava/util/Optional;)V
public fun addUser (Lme/proton/core/user/domain/entity/User;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun changePassword (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun changePassword (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun getAddresses (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun getUser (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun lock (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -1002,7 +1002,7 @@ public final class me/proton/core/user/data/repository/UserRepositoryImpl : me/p
public fun removeLockedAndPasswordScopes (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun setPassphrase (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/keystore/EncryptedByteArray;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun unlockUserForLockedScope (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun unlockUserForPasswordScope (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun unlockUserForPasswordScope (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateUser (Lme/proton/core/user/domain/entity/User;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateUserUsedBaseSpace (Lme/proton/core/domain/entity/UserId;JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateUserUsedDriveSpace (Lme/proton/core/domain/entity/UserId;JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -209,8 +209,7 @@ class UserManagerPasswordTests {
keySalt = any(),
srpProofs = any(),
srpSession = any(),
secondFactorCode = null,
secondFactorFido = null,
secondFactorProof = null,
auth = any(),
keys = null,
userKeys = emptyList()
@@ -228,8 +227,7 @@ class UserManagerPasswordTests {
),
srpSession = "test-srp-session",
auth = mockk(),
secondFactorCode = null,
secondFactorFido = null
secondFactorProof = null
)
// THEN
@@ -42,7 +42,7 @@ import me.proton.core.auth.domain.exception.InvalidServerAuthenticationException
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialDescriptor
import me.proton.core.auth.fido.domain.entity.Fido2PublicKeyCredentialRequestOptions
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.challenge.domain.entity.ChallengeFrameDetails
import me.proton.core.crypto.android.context.AndroidCryptoContext
import me.proton.core.crypto.common.context.CryptoContext
@@ -483,7 +483,6 @@ class UserRepositoryImplTests {
TestUsers.User1.id,
testSrpProofs,
"test-srp-session",
null,
null
)
assertNotNull(response)
@@ -514,8 +513,7 @@ class UserRepositoryImplTests {
TestUsers.User1.id,
testSrpProofs,
"test-srp-session",
"test-2fa",
null
SecondFactorProof.SecondFactorCode("test-2fa")
)
assertNotNull(response)
assertTrue(response)
@@ -544,8 +542,7 @@ class UserRepositoryImplTests {
TestUsers.User1.id,
testSrpProofs,
"test-srp-session",
null,
SecondFactorFido(
SecondFactorProof.Fido2(
publicKeyOptions = Fido2PublicKeyCredentialRequestOptions(
challenge = challenge,
allowCredentials = listOf(
@@ -20,7 +20,7 @@ package me.proton.core.user.data
import kotlinx.coroutines.flow.Flow
import me.proton.core.accountrecovery.domain.repository.AccountRecoveryRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.EncryptedByteArray
import me.proton.core.crypto.common.keystore.EncryptedString
@@ -142,8 +142,7 @@ class UserManagerImpl @Inject constructor(
override suspend fun changePassword(
userId: UserId,
newPassword: EncryptedString,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
proofs: SrpProofs,
srpSession: String,
auth: Auth?
@@ -169,8 +168,7 @@ class UserManagerImpl @Inject constructor(
keySalt = keySalt,
srpProofs = proofs,
srpSession = srpSession,
secondFactorCode = secondFactorCode,
secondFactorFido = secondFactorFido,
secondFactorProof = secondFactorProof,
auth = auth,
keys = updatedKeys,
userKeys = updatedUserKeys
@@ -27,10 +27,11 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import me.proton.core.auth.data.api.request.toFido2Request
import me.proton.core.auth.data.api.request.toSecondFactorCode
import me.proton.core.auth.data.api.request.toSecondFactorFido
import me.proton.core.auth.data.api.response.isSuccess
import me.proton.core.auth.domain.usecase.ValidateServerProof
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.challenge.data.frame.ChallengeFrame
import me.proton.core.challenge.domain.entity.ChallengeFrameDetails
import me.proton.core.challenge.domain.framePrefix
@@ -200,16 +201,15 @@ class UserRepositoryImpl @Inject constructor(
sessionUserId: SessionUserId,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): Boolean = result("unlockUserForPasswordScope") {
provider.get<UserApi>(sessionUserId).invoke {
val request = UnlockPasswordRequest(
srpProofs.clientEphemeral,
srpProofs.clientProof,
srpSession,
secondFactorCode,
secondFactorFido?.toFido2Request()
clientEphemeral = srpProofs.clientEphemeral,
clientProof = srpProofs.clientProof,
srpSession = srpSession,
twoFactorCode = secondFactorProof.toSecondFactorCode(),
fido2 = secondFactorProof.toSecondFactorFido()
)
val response = unlockPasswordScope(request)
validateServerProof(
@@ -28,6 +28,7 @@ import io.mockk.unmockkStatic
import io.mockk.verify
import kotlinx.coroutines.test.runTest
import me.proton.core.accountrecovery.domain.repository.AccountRecoveryRepository
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.EncryptedByteArray
import me.proton.core.crypto.common.keystore.PlainByteArray
@@ -269,8 +270,7 @@ class UserManagerImplTest {
val result = spyManager.changePassword(
userId = userIdMigrated,
newPassword = "encrypted",
secondFactorCode = "code",
secondFactorFido = null,
secondFactorProof = SecondFactorProof.SecondFactorCode("code"),
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
@@ -291,8 +291,7 @@ class UserManagerImplTest {
manager.changePassword(
userId = userIdMigrated,
newPassword = "encrypted",
secondFactorCode = "code",
secondFactorFido = null,
secondFactorProof = SecondFactorProof.SecondFactorCode("code"),
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
@@ -304,8 +303,7 @@ class UserManagerImplTest {
keySalt = any(),
srpProofs = any(),
srpSession = any(),
secondFactorCode = any(),
secondFactorFido = null,
secondFactorProof = any(),
auth = any(),
keys = null,
userKeys = expectedUserKeys,
@@ -322,8 +320,7 @@ class UserManagerImplTest {
manager.changePassword(
userId = userIdNotMigrated,
newPassword = "encrypted",
secondFactorCode = "code",
secondFactorFido = null,
secondFactorProof = SecondFactorProof.SecondFactorCode("code"),
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
@@ -335,8 +332,7 @@ class UserManagerImplTest {
keySalt = any(),
srpProofs = any(),
srpSession = any(),
secondFactorCode = any(),
secondFactorFido = null,
secondFactorProof = any(),
auth = any(),
keys = expectedUserKeys + expectedAddressKeys,
userKeys = null,
@@ -350,8 +346,7 @@ class UserManagerImplTest {
manager.changePassword(
userId = userIdMigrated,
newPassword = "encrypted",
secondFactorCode = "code",
secondFactorFido = null,
secondFactorProof = SecondFactorProof.SecondFactorCode("code"),
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
@@ -363,8 +358,7 @@ class UserManagerImplTest {
keySalt = any(),
srpProofs = any(),
srpSession = any(),
secondFactorCode = any(),
secondFactorFido = null,
secondFactorProof = any(),
auth = any(),
keys = any(),
userKeys = any(),
+2 -2
View File
@@ -51,7 +51,7 @@ public final class me/proton/core/user/domain/UserAddressManager$DefaultImpls {
public abstract interface class me/proton/core/user/domain/UserManager {
public abstract fun addUser (Lme/proton/core/user/domain/entity/User;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun changePassword (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun changePassword (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getAddresses (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getUser (Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun lock (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -550,7 +550,7 @@ public abstract interface class me/proton/core/user/domain/repository/UserReposi
public abstract fun observeUser (Lme/proton/core/domain/entity/UserId;Z)Lkotlinx/coroutines/flow/Flow;
public abstract fun removeLockedAndPasswordScopes (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun unlockUserForLockedScope (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun unlockUserForPasswordScope (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorFido;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun unlockUserForPasswordScope (Lme/proton/core/domain/entity/UserId;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/auth/fido/domain/entity/SecondFactorProof;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateUser (Lme/proton/core/user/domain/entity/User;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateUserUsedBaseSpace (Lme/proton/core/domain/entity/UserId;JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateUserUsedDriveSpace (Lme/proton/core/domain/entity/UserId;JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -19,7 +19,7 @@
package me.proton.core.user.domain
import kotlinx.coroutines.flow.Flow
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.crypto.common.keystore.EncryptedByteArray
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.keystore.PlainByteArray
@@ -135,8 +135,7 @@ interface UserManager {
suspend fun changePassword(
userId: UserId,
newPassword: EncryptedString,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?,
secondFactorProof: SecondFactorProof?,
proofs: SrpProofs,
srpSession: String,
auth: Auth?
@@ -19,7 +19,7 @@
package me.proton.core.user.domain.repository
import kotlinx.coroutines.flow.Flow
import me.proton.core.auth.fido.domain.entity.SecondFactorFido
import me.proton.core.auth.fido.domain.entity.SecondFactorProof
import me.proton.core.challenge.domain.entity.ChallengeFrameDetails
import me.proton.core.crypto.common.keystore.EncryptedString
import me.proton.core.crypto.common.srp.Auth
@@ -153,8 +153,7 @@ interface UserRepository : PassphraseRepository {
sessionUserId: SessionUserId,
srpProofs: SrpProofs,
srpSession: String,
secondFactorCode: String?,
secondFactorFido: SecondFactorFido?
secondFactorProof: SecondFactorProof?
): Boolean
/**