fix(user): Removed Organization Keys support (deprecated).

This commit is contained in:
Neil Marietta 2024-04-19 15:46:33 +02:00 committed by MargeBot
parent 6ec99275e5
commit bbcc15eb6c
26 changed files with 42 additions and 138 deletions

View File

@ -15,18 +15,16 @@ public final class me/proton/core/accountrecovery/data/IsAccountRecoveryResetEna
public final class me/proton/core/accountrecovery/data/api/request/ResetPasswordRequest {
public static final field Companion Lme/proton/core/accountrecovery/data/api/request/ResetPasswordRequest$Companion;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/util/List;
public final fun component4 ()Lme/proton/core/key/data/api/request/AuthRequest;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;)Lme/proton/core/accountrecovery/data/api/request/ResetPasswordRequest;
public static synthetic fun copy$default (Lme/proton/core/accountrecovery/data/api/request/ResetPasswordRequest;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;ILjava/lang/Object;)Lme/proton/core/accountrecovery/data/api/request/ResetPasswordRequest;
public final fun component2 ()Ljava/util/List;
public final fun component3 ()Lme/proton/core/key/data/api/request/AuthRequest;
public final fun copy (Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;)Lme/proton/core/accountrecovery/data/api/request/ResetPasswordRequest;
public static synthetic fun copy$default (Lme/proton/core/accountrecovery/data/api/request/ResetPasswordRequest;Ljava/lang/String;Ljava/util/List;Lme/proton/core/key/data/api/request/AuthRequest;ILjava/lang/Object;)Lme/proton/core/accountrecovery/data/api/request/ResetPasswordRequest;
public fun equals (Ljava/lang/Object;)Z
public final fun getAuth ()Lme/proton/core/key/data/api/request/AuthRequest;
public final fun getKeySalt ()Ljava/lang/String;
public final fun getOrganizationKey ()Ljava/lang/String;
public final fun getUserKeys ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
@ -50,7 +48,7 @@ public final class me/proton/core/accountrecovery/data/api/request/ResetPassword
public final class me/proton/core/accountrecovery/data/repository/AccountRecoveryRepositoryImpl : me/proton/core/accountrecovery/domain/repository/AccountRecoveryRepository {
public fun <init> (Lme/proton/core/network/data/ApiProvider;Lme/proton/core/auth/domain/usecase/ValidateServerProof;)V
public fun cancelRecoveryAttempt (Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun resetPassword (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 resetPassword (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/util/List;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun startRecovery (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

View File

@ -27,8 +27,6 @@ import me.proton.core.key.data.api.request.PrivateKeyRequest
public data class ResetPasswordRequest(
@SerialName("KeySalt")
val keySalt: String,
@SerialName("OrganizationKey")
val organizationKey: String?,
@SerialName("UserKeys")
val userKeys: List<PrivateKeyRequest>? = null,
@SerialName("Auth")

View File

@ -73,14 +73,12 @@ public class AccountRecoveryRepositoryImpl @Inject constructor(
override suspend fun resetPassword(
sessionUserId: UserId,
keySalt: String,
organizationKey: String?,
userKeys: List<Key>?,
auth: Auth?
): Boolean = result("account_recovery.reset") {
apiProvider.get<AccountRecoveryApi>(sessionUserId).invoke {
val request = ResetPasswordRequest(
keySalt = keySalt,
organizationKey = organizationKey,
userKeys = userKeys?.map {
PrivateKeyRequest(privateKey = it.privateKey, id = it.keyId.id)
},

View File

@ -24,7 +24,6 @@ import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.justRun
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import me.proton.core.accountrecovery.data.api.AccountRecoveryApi
import me.proton.core.accountrecovery.data.api.response.CancelRecoveryAttemptResponse
import me.proton.core.auth.domain.usecase.ValidateServerProof
@ -142,7 +141,6 @@ class AccountRecoveryRepositoryImplTest {
val result = tested.resetPassword(
sessionUserId = testUserId,
keySalt = "test-key-salt",
organizationKey = null,
userKeys = null,
auth = null
)
@ -167,7 +165,6 @@ class AccountRecoveryRepositoryImplTest {
val result = tested.resetPassword(
sessionUserId = testUserId,
keySalt = "test-key-salt",
organizationKey = null,
userKeys = null,
auth = null
)
@ -192,7 +189,6 @@ class AccountRecoveryRepositoryImplTest {
val result = tested.resetPassword(
sessionUserId = testUserId,
keySalt = "test-key-salt",
organizationKey = "test-org-key",
userKeys = listOf(
Key(keyId = KeyId("test-key-id-1"), privateKey = "test-private-key-armored")
),

View File

@ -6,7 +6,7 @@ public abstract interface class me/proton/core/accountrecovery/domain/IsAccountR
public abstract interface class me/proton/core/accountrecovery/domain/repository/AccountRecoveryRepository {
public abstract fun cancelRecoveryAttempt (Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun resetPassword (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 resetPassword (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/util/List;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun startRecovery (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

View File

@ -52,7 +52,6 @@ public interface AccountRecoveryRepository {
public suspend fun resetPassword(
sessionUserId: UserId,
keySalt: String,
organizationKey: String?,
userKeys: List<Key>?,
auth: Auth?
): Boolean

View File

@ -219,8 +219,8 @@ public final class me/proton/core/key/data/api/request/SignedKeyListRequest$Comp
public final class me/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest {
public static final field Companion Lme/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest$Companion;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
@ -229,16 +229,14 @@ public final class me/proton/core/key/data/api/request/UpdateKeysForPasswordChan
public final fun component6 ()Lme/proton/core/key/data/api/request/AuthRequest;
public final fun component7 ()Ljava/util/List;
public final fun component8 ()Ljava/util/List;
public final fun component9 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;Ljava/lang/String;)Lme/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest;
public static synthetic fun copy$default (Lme/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;)Lme/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest;
public static synthetic fun copy$default (Lme/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/key/data/api/request/AuthRequest;Ljava/util/List;Ljava/util/List;ILjava/lang/Object;)Lme/proton/core/key/data/api/request/UpdateKeysForPasswordChangeRequest;
public fun equals (Ljava/lang/Object;)Z
public final fun getAuth ()Lme/proton/core/key/data/api/request/AuthRequest;
public final fun getClientEphemeral ()Ljava/lang/String;
public final fun getClientProof ()Ljava/lang/String;
public final fun getKeySalt ()Ljava/lang/String;
public final fun getKeys ()Ljava/util/List;
public final fun getOrganizationKey ()Ljava/lang/String;
public final fun getSrpSession ()Ljava/lang/String;
public final fun getTwoFactorCode ()Ljava/lang/String;
public final fun getUserKeys ()Ljava/util/List;
@ -1007,7 +1005,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/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Ljava/lang/String;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/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 {

View File

@ -38,9 +38,7 @@ data class UpdateKeysForPasswordChangeRequest(
@SerialName("Keys")
val keys: List<PrivateKeyRequest>? = null,
@SerialName("UserKeys")
val userKeys: List<PrivateKeyRequest>? = null,
@SerialName("OrganizationKey")
val organizationKey: String?
val userKeys: List<PrivateKeyRequest>? = null
)
@Serializable

View File

@ -103,8 +103,7 @@ class PrivateKeyRepositoryImpl @Inject constructor(
secondFactorCode: String,
auth: Auth?,
keys: List<Key>?,
userKeys: List<Key>?,
organizationKey: String?
userKeys: List<Key>?
): Boolean {
return provider.get<KeyApi>(sessionUserId).invoke {
val response = updatePrivateKeys(
@ -120,8 +119,7 @@ class PrivateKeyRepositoryImpl @Inject constructor(
},
userKeys = userKeys?.map {
PrivateKeyRequest(privateKey = it.privateKey, id = it.keyId.id)
},
organizationKey = organizationKey
}
)
)
validateServerProof(response.serverProof, srpProofs.expectedServerProof) { "key update failed" }

View File

@ -109,8 +109,7 @@ class PrivateKeyRepositoryImplTest {
secondFactorCode = "test-2fa-code",
auth = mockk(relaxed = true),
keys = listOf(mockk(relaxed = true)),
userKeys = listOf(mockk(relaxed = true)),
organizationKey = "test-org-key"
userKeys = listOf(mockk(relaxed = true))
)
}
}

View File

@ -656,11 +656,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/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Ljava/lang/String;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/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/crypto/common/srp/Auth;Ljava/util/List;Ljava/util/List;Ljava/lang/String;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;Ljava/lang/String;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 {

View File

@ -58,8 +58,7 @@ interface PrivateKeyRepository {
secondFactorCode: String,
auth: Auth?,
keys: List<Key>? = null,
userKeys: List<Key>? = null,
organizationKey: String?
userKeys: List<Key>? = null
): Boolean
suspend fun reactivatePrivateKey(

View File

@ -404,7 +404,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;Lme/proton/core/usersettings/domain/repository/OrganizationRepository;)V
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;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun invoke$default (Lme/proton/core/usersettings/domain/usecase/PerformUpdateUserPassword;ZLme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
}

View File

@ -28,8 +28,8 @@ protonBuild {
}
protonCoverage {
branchCoveragePercentage.set(39)
lineCoveragePercentage.set(72)
branchCoveragePercentage.set(44)
lineCoveragePercentage.set(73)
}
publishOption.shouldBePublishedAsLib = true

View File

@ -36,11 +36,13 @@ interface OrganizationRepository {
refresh: Boolean = false
): Organization
@Deprecated("Organization Keys should not be needed or updated from Mobile clients.")
fun getOrganizationKeysFlow(
sessionUserId: SessionUserId,
refresh: Boolean = false
): Flow<DataResult<OrganizationKeys>>
@Deprecated("Organization Keys should not be needed or updated from Mobile clients.")
suspend fun getOrganizationKeys(
sessionUserId: SessionUserId,
refresh: Boolean = false

View File

@ -27,11 +27,8 @@ import me.proton.core.crypto.common.keystore.use
import me.proton.core.crypto.common.srp.SrpProofs
import me.proton.core.domain.entity.UserId
import me.proton.core.user.domain.UserManager
import me.proton.core.user.domain.extension.isOrganizationAdmin
import me.proton.core.user.domain.extension.nameNotNull
import me.proton.core.user.domain.repository.UserRepository
import me.proton.core.usersettings.domain.repository.OrganizationRepository
import me.proton.core.util.kotlin.takeIfNotEmpty
import javax.inject.Inject
class PerformUpdateUserPassword @Inject constructor(
@ -39,8 +36,7 @@ class PerformUpdateUserPassword @Inject constructor(
private val accountRepository: AccountRepository,
private val authRepository: AuthRepository,
private val userManager: UserManager,
private val userRepository: UserRepository,
private val organizationRepository: OrganizationRepository,
private val userRepository: UserRepository
) {
private val keyStore = context.keyStoreCrypto
private val srp = context.srpCrypto
@ -58,9 +54,6 @@ class PerformUpdateUserPassword @Inject constructor(
val sessionId = requireNotNull(account?.sessionId)
val loginInfo = authRepository.getAuthInfoSrp(sessionId, username)
val modulus = authRepository.randomModulus(sessionId)
val organizationKeys = if (user.isOrganizationAdmin())
organizationRepository.getOrganizationKeys(userId, refresh = true)
else null
loginPassword.decrypt(keyStore).toByteArray().use { decryptedLoginPassword ->
newPassword.decrypt(keyStore).toByteArray().use { decryptedNewPassword ->
val clientProofs: SrpProofs = srp.generateSrpProofs(
@ -85,8 +78,7 @@ class PerformUpdateUserPassword @Inject constructor(
secondFactorCode = secondFactorCode,
proofs = clientProofs,
srpSession = loginInfo.srpSession,
auth = auth,
orgPrivateKey = organizationKeys?.privateKey?.takeIfNotEmpty()
auth = auth
)
}
}

View File

@ -37,7 +37,6 @@ import me.proton.core.user.domain.entity.Role
import me.proton.core.user.domain.entity.Type
import me.proton.core.user.domain.entity.User
import me.proton.core.user.domain.repository.UserRepository
import me.proton.core.usersettings.domain.repository.OrganizationRepository
import org.junit.Before
import org.junit.Test
import kotlin.test.assertFailsWith
@ -49,7 +48,6 @@ class PerformResetUserPasswordTest {
private val accountRepository = mockk<AccountRepository>(relaxed = true)
private val authRepository = mockk<AuthRepository>(relaxed = true)
private val userRepository = mockk<UserRepository>(relaxed = true)
private val organizationRepository = mockk<OrganizationRepository>(relaxed = true)
private val srpCrypto = mockk<SrpCrypto>(relaxed = true)
private val keyStoreCrypto = mockk<KeyStoreCrypto>(relaxed = true)
private val cryptoContext = mockk<CryptoContext>(relaxed = true)
@ -113,7 +111,6 @@ class PerformResetUserPasswordTest {
modulus = testModulus
)
coEvery { organizationRepository.getOrganizationKeys(testUserId, any()) } returns mockk()
every { cryptoContext.pgpCrypto } returns testPGPCrypto
every {
@ -234,15 +231,6 @@ class PerformResetUserPasswordTest {
fun `reset password organization admin`() = runTest {
coEvery { userRepository.getUser(testUserId) } returns testUser.copy(role = Role.OrganizationAdmin)
coEvery {
organizationRepository.getOrganizationKeys(
sessionUserId = testUserId,
refresh = any()
)
} returns mockk {
every { privateKey } returns "armored-private-key"
}
coEvery {
userManager.resetPassword(
sessionUserId = testUserId,

View File

@ -37,7 +37,6 @@ import me.proton.core.user.domain.UserManager
import me.proton.core.user.domain.entity.Type
import me.proton.core.user.domain.entity.User
import me.proton.core.user.domain.repository.UserRepository
import me.proton.core.usersettings.domain.repository.OrganizationRepository
import org.junit.Before
import org.junit.Test
import kotlin.test.assertFailsWith
@ -47,7 +46,6 @@ class PerformUpdateUserPasswordTest {
private val accountRepository = mockk<AccountRepository>(relaxed = true)
private val authRepository = mockk<AuthRepository>(relaxed = true)
private val userRepository = mockk<UserRepository>(relaxed = true)
private val organizationRepository = mockk<OrganizationRepository>(relaxed = true)
private val srpCrypto = mockk<SrpCrypto>(relaxed = true)
private val keyStoreCrypto = mockk<KeyStoreCrypto>(relaxed = true)
private val cryptoContext = mockk<CryptoContext>(relaxed = true)
@ -111,7 +109,6 @@ class PerformUpdateUserPasswordTest {
accountRepository = accountRepository,
authRepository = authRepository,
userRepository = userRepository,
organizationRepository = organizationRepository,
userManager = userManager
)
@ -122,8 +119,7 @@ class PerformUpdateUserPasswordTest {
secondFactorCode = any(),
proofs = any(),
srpSession = any(),
auth = any(),
orgPrivateKey = any()
auth = any()
)
} returns true
@ -144,7 +140,6 @@ class PerformUpdateUserPasswordTest {
modulusId = testModulusId,
modulus = testModulus
)
coEvery { organizationRepository.getOrganizationKeys(testUserId, any()) } returns mockk()
every { cryptoContext.pgpCrypto } returns testPGPCrypto
every {
testPGPCrypto.generateNewKeySalt()

View File

@ -187,9 +187,9 @@ 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/usersettings/domain/repository/OrganizationRepository;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 <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/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun changePassword (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;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;
@ -203,11 +203,11 @@ public final class me/proton/core/user/data/UserManagerImpl : me/proton/core/use
}
public final class me/proton/core/user/data/UserManagerImpl_Factory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;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;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/user/data/UserManagerImpl_Factory;
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;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;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/user/data/UserManagerImpl_Factory;
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Lme/proton/core/user/data/UserManagerImpl;
public static fun newInstance (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/usersettings/domain/repository/OrganizationRepository;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;)Lme/proton/core/user/data/UserManagerImpl;
public static fun newInstance (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;)Lme/proton/core/user/data/UserManagerImpl;
}
public final class me/proton/core/user/data/UserSpaceEvent {

View File

@ -30,7 +30,7 @@ protonBuild {
}
protonCoverage {
branchCoveragePercentage.set(35)
branchCoveragePercentage.set(34)
lineCoveragePercentage.set(37)
}

View File

@ -72,13 +72,11 @@ import me.proton.core.user.domain.SignedKeyListChangeListener
import me.proton.core.user.domain.UserManager
import me.proton.core.user.domain.extension.primary
import me.proton.core.user.domain.repository.PassphraseRepository
import me.proton.core.usersettings.domain.repository.OrganizationRepository
import me.proton.core.user.domain.repository.UserLocalDataSource
import me.proton.core.user.domain.repository.UserRemoteDataSource
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import java.util.Optional
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@ -104,9 +102,6 @@ UserManagerImplTests {
@MockK(relaxed = true)
private lateinit var keyStoreCrypto: KeyStoreCrypto
@MockK(relaxed = true)
private lateinit var organizationRepository: OrganizationRepository
@MockK(relaxed = true)
private lateinit var accountRecoveryRepository: AccountRecoveryRepository
@ -199,7 +194,6 @@ UserManagerImplTests {
passphraseRepository,
keySaltRepository,
privateKeyRepository,
organizationRepository,
accountRecoveryRepository,
userAddressKeySecretProvider,
cryptoContext,

View File

@ -59,7 +59,6 @@ import me.proton.core.user.domain.entity.UserKey
import me.proton.core.user.domain.repository.PassphraseRepository
import me.proton.core.user.domain.repository.UserAddressRepository
import me.proton.core.user.domain.repository.UserRepository
import me.proton.core.usersettings.domain.repository.OrganizationRepository
import org.junit.After
import org.junit.Before
import org.junit.Test
@ -76,7 +75,6 @@ class UserManagerPasswordTests {
private val passphraseRepository: PassphraseRepository = mockk(relaxed = true)
private val keySaltRepository: KeySaltRepositoryImpl = mockk(relaxed = true)
private val privateKeyRepository: PrivateKeyRepository = mockk(relaxed = true)
private val organizationRepository: OrganizationRepository = mockk(relaxed = true)
private val accountRecoveryRepository: AccountRecoveryRepository = mockk(relaxed = true)
private val generateSignedKeyList: GenerateSignedKeyList = mockk()
private val signedKeyListChangeListener: SignedKeyListChangeListener = mockk()
@ -158,7 +156,6 @@ class UserManagerPasswordTests {
passphraseRepository,
keySaltRepository,
privateKeyRepository,
organizationRepository,
accountRecoveryRepository,
userAddressKeySecretProvider,
cryptoContext,
@ -194,7 +191,6 @@ class UserManagerPasswordTests {
val userKey1 = mockk<UserKey>(relaxed = true)
every { userKey1.updatePrivateKeyPassphraseOrNull(any(), any()) } returns null
coEvery { organizationRepository.getOrganizationKeys(any(), any()) } returns mockk(relaxed = true)
val mockedUser = mockk<User>(relaxed = true).also {
every { it.keys } returns listOf(userKey1)
@ -216,7 +212,6 @@ class UserManagerPasswordTests {
any(),
any(),
any(),
any(),
any()
)
} returns true
@ -231,7 +226,6 @@ class UserManagerPasswordTests {
expectedServerProof = "expected-server-proof"
),
srpSession = "test-srp-session",
orgPrivateKey = "org-private-key",
auth = mockk()
)

View File

@ -27,7 +27,6 @@ import me.proton.core.crypto.common.keystore.PlainByteArray
import me.proton.core.crypto.common.keystore.decrypt
import me.proton.core.crypto.common.keystore.encrypt
import me.proton.core.crypto.common.keystore.use
import me.proton.core.crypto.common.pgp.Armored
import me.proton.core.crypto.common.srp.Auth
import me.proton.core.crypto.common.srp.SrpProofs
import me.proton.core.domain.entity.SessionUserId
@ -50,12 +49,9 @@ import me.proton.core.user.domain.entity.User
import me.proton.core.user.domain.entity.UserAddress
import me.proton.core.user.domain.extension.generateNewKeyFormat
import me.proton.core.user.domain.extension.hasMigratedKey
import me.proton.core.user.domain.extension.isOrganizationAdmin
import me.proton.core.user.domain.repository.PassphraseRepository
import me.proton.core.user.domain.repository.UserAddressRepository
import me.proton.core.user.domain.repository.UserRepository
import me.proton.core.usersettings.domain.repository.OrganizationRepository
import me.proton.core.util.kotlin.takeIfNotEmpty
import java.util.Optional
import javax.inject.Inject
import javax.inject.Singleton
@ -67,7 +63,6 @@ class UserManagerImpl @Inject constructor(
private val passphraseRepository: PassphraseRepository,
private val keySaltRepository: KeySaltRepository,
private val privateKeyRepository: PrivateKeyRepository,
private val organizationRepository: OrganizationRepository,
private val accountRecoveryRepository: AccountRecoveryRepository,
private val userAddressKeySecretProvider: UserAddressKeySecretProvider,
private val cryptoContext: CryptoContext,
@ -149,8 +144,7 @@ class UserManagerImpl @Inject constructor(
secondFactorCode: String,
proofs: SrpProofs,
srpSession: String,
auth: Auth?,
orgPrivateKey: Armored?
auth: Auth?
): Boolean {
newPassword.decrypt(keyStore).toByteArray().use { decryptedNewPassword ->
val keySalt = pgp.generateNewKeySalt()
@ -167,13 +161,6 @@ class UserManagerImpl @Inject constructor(
val updatedKeys = user.keys.takeUnless { isUserMigrated }?.plus(addresses.flatMap { it.keys })
?.mapNotNull { it.updatePrivateKeyPassphraseOrNull(cryptoContext, newPassphrase.array) }
// Update organization key if provided.
val updatedOrgPrivateKey = orgPrivateKey?.takeIf { user.isOrganizationAdmin() }?.let { key ->
requireNotNull(passphraseRepository.getPassphrase(userId)).decrypt(keyStore).use {
key.updatePrivateKeyPassphraseOrNull(cryptoContext, it.array, newPassphrase.array)
}
}
// Update all needed keys providing any authentication proof.
val result = privateKeyRepository.updatePrivateKeys(
sessionUserId = userId,
@ -183,8 +170,7 @@ class UserManagerImpl @Inject constructor(
secondFactorCode = secondFactorCode,
auth = auth,
keys = updatedKeys,
userKeys = updatedUserKeys,
organizationKey = updatedOrgPrivateKey
userKeys = updatedUserKeys
)
refreshUser(userId, newPassphrase.encrypt(keyStore))
@ -346,11 +332,6 @@ class UserManagerImpl @Inject constructor(
val addresses = userAddressRepository.getAddresses(sessionUserId, refresh = true)
val user = userRepository.getUser(sessionUserId, refresh = true)
val isUserMigrated = addresses.hasMigratedKey()
val organizationKeys = if (user.isOrganizationAdmin())
organizationRepository.getOrganizationKeys(sessionUserId, refresh = true)
else null
val updatedUserKeys = user.keys.takeIf { isUserMigrated }
?.mapNotNull { it.updatePrivateKeyPassphraseOrNull(cryptoContext, newPassphrase.array) }
@ -358,8 +339,7 @@ class UserManagerImpl @Inject constructor(
sessionUserId = sessionUserId,
auth = auth,
keySalt = keySalt,
userKeys = updatedUserKeys,
organizationKey = organizationKeys?.privateKey?.takeIfNotEmpty()
userKeys = updatedUserKeys
)
refreshUser(sessionUserId, newPassphrase.encrypt(keyStore))

View File

@ -38,7 +38,6 @@ import me.proton.core.key.domain.entity.key.Key
import me.proton.core.key.domain.entity.key.KeyId
import me.proton.core.key.domain.entity.key.PrivateKey
import me.proton.core.key.domain.entity.key.PrivateKeySalt
import me.proton.core.key.domain.extension.keyHolder
import me.proton.core.key.domain.extension.updatePrivateKeyPassphraseOrNull
import me.proton.core.key.domain.repository.KeySaltRepository
import me.proton.core.key.domain.repository.PrivateKeyRepository
@ -52,8 +51,6 @@ import me.proton.core.user.domain.entity.UserKey
import me.proton.core.user.domain.repository.PassphraseRepository
import me.proton.core.user.domain.repository.UserAddressRepository
import me.proton.core.user.domain.repository.UserRepository
import me.proton.core.usersettings.domain.repository.OrganizationRepository
import me.proton.core.util.kotlin.any
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertFalse
@ -129,7 +126,6 @@ class UserManagerImplTest {
coEvery { this@mockk.getKeySalts(any(), any()) } returns listOf(privateKeySalt)
}
private val privateKeyRepository: PrivateKeyRepository = mockk(relaxed = true)
private val organizationRepository: OrganizationRepository = mockk(relaxed = true)
private val accountRecoveryRepository: AccountRecoveryRepository = mockk(relaxed = true)
private val userAddressKeySecretProvider: UserAddressKeySecretProvider = mockk(relaxed = true)
private val pgpCryptoMock: PGPCrypto = mockk(relaxed = true) {
@ -154,8 +150,7 @@ class UserManagerImplTest {
userAddressKeySecretProvider = userAddressKeySecretProvider,
cryptoContext = cryptoContext,
generateSignedKeyList = mockk(relaxed = true),
signedKeyListChangeListener = mockk(relaxed = true),
organizationRepository = organizationRepository
signedKeyListChangeListener = mockk(relaxed = true)
)
}
@ -278,7 +273,6 @@ class UserManagerImplTest {
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
orgPrivateKey = null
)
// Then
assertFalse(result)
@ -300,7 +294,6 @@ class UserManagerImplTest {
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
orgPrivateKey = null
)
// Then
coVerify {
@ -313,7 +306,6 @@ class UserManagerImplTest {
auth = any(),
keys = null,
userKeys = expectedUserKeys,
organizationKey = null
)
}
}
@ -331,7 +323,6 @@ class UserManagerImplTest {
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
orgPrivateKey = null
)
// Then
coVerify {
@ -344,15 +335,12 @@ class UserManagerImplTest {
auth = any(),
keys = expectedUserKeys + expectedAddressKeys,
userKeys = null,
organizationKey = null
)
}
}
@Test
fun changePasswordOrgPrivateKey() = runTest {
// Given
val orgKey = "orgKey"
// When
manager.changePassword(
userId = userIdMigrated,
@ -361,7 +349,6 @@ class UserManagerImplTest {
proofs = mockk(),
srpSession = "srp",
auth = mockk(),
orgPrivateKey = orgKey
)
// Then
coVerify {
@ -374,7 +361,6 @@ class UserManagerImplTest {
auth = any(),
keys = any(),
userKeys = any(),
organizationKey = orgKey
)
}
}
@ -400,9 +386,6 @@ class UserManagerImplTest {
mockkStatic("me.proton.core.key.domain.extension.UpdatePrivateKeyKt")
every { userPrimaryKey.updatePrivateKeyPassphraseOrNull(any(), any()) } returns mockk(relaxed = true)
coEvery { pgpCryptoMock.generateNewKeySalt() } returns "test-key-salt"
coEvery { organizationRepository.getOrganizationKeys(userIdMigrated, any()) } returns mockk {
every { privateKey } returns "org-private-key"
}
// When
manager.resetPassword(
sessionUserId = userIdMigrated,
@ -412,12 +395,10 @@ class UserManagerImplTest {
// Then
coVerify { userAddressRepository.getAddresses(userIdMigrated, refresh = true) }
coVerify { userRepository.getUser(userIdMigrated, refresh = true) }
coVerify { organizationRepository.getOrganizationKeys(userIdMigrated, any()) }
coVerify {
accountRecoveryRepository.resetPassword(
userIdMigrated,
"test-key-salt",
"org-private-key",
any(),
any()
)
@ -440,7 +421,6 @@ class UserManagerImplTest {
// Then
coVerify { userAddressRepository.getAddresses(userIdNotMigrated, refresh = true) }
coVerify { userRepository.getUser(userIdNotMigrated, refresh = true) }
coVerify(exactly = 0) { organizationRepository.getOrganizationKeys(any(), any()) }
verify(exactly = 0) { userPrimaryKey.updatePrivateKeyPassphraseOrNull(any(), any()) }
unmockkStatic("me.proton.core.key.domain.extension.UpdatePrivateKeyKt")
}
@ -483,8 +463,7 @@ class UserManagerImplTest {
userAddressKeySecretProvider = userAddressKeySecretProvider,
cryptoContext = cryptoContext,
generateSignedKeyList = mockk(relaxed = true),
signedKeyListChangeListener = mockk(relaxed = true),
organizationRepository = organizationRepository
signedKeyListChangeListener = mockk(relaxed = true)
)
// When
val result = manager.reactivateKey(userIdMigrated, KeyId("user-key-id"), testPrivateKeyMock)

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/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Ljava/lang/String;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/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;
@ -65,7 +65,7 @@ public abstract interface class me/proton/core/user/domain/UserManager {
}
public final class me/proton/core/user/domain/UserManager$DefaultImpls {
public static synthetic fun changePassword$default (Lme/proton/core/user/domain/UserManager;Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static synthetic fun changePassword$default (Lme/proton/core/user/domain/UserManager;Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Ljava/lang/String;Lme/proton/core/crypto/common/srp/SrpProofs;Ljava/lang/String;Lme/proton/core/crypto/common/srp/Auth;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static synthetic fun getAddresses$default (Lme/proton/core/user/domain/UserManager;Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static synthetic fun getUser$default (Lme/proton/core/user/domain/UserManager;Lme/proton/core/domain/entity/UserId;ZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static synthetic fun observeAddresses$default (Lme/proton/core/user/domain/UserManager;Lme/proton/core/domain/entity/UserId;ZILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;

View File

@ -142,8 +142,7 @@ interface UserManager {
secondFactorCode: String = "",
proofs: SrpProofs,
srpSession: String,
auth: Auth?,
orgPrivateKey: Armored?
auth: Auth?
): Boolean
/**