Skip to content

Commit

Permalink
Merge branch 'develop' into dependabot/github_actions/codecov/codecov…
Browse files Browse the repository at this point in the history
…-action-3
  • Loading branch information
yamilmedina authored Oct 23, 2023
2 parents f8ce69c + 872981a commit ed9dbde
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,22 @@ import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.flatMap
import com.wire.kalium.logic.functional.fold
import com.wire.kalium.logic.kaliumLogger
import com.wire.kalium.util.KaliumDispatcher
import com.wire.kalium.util.KaliumDispatcherImpl
import kotlinx.coroutines.withContext

interface E2EClientProvider {
interface E2EIClientProvider {
suspend fun getE2EIClient(clientId: ClientId? = null): Either<CoreFailure, E2EIClient>
}

internal class E2EIClientProviderImpl(
internal class EI2EIClientProviderImpl(
private val userId: UserId,
private val currentClientIdProvider: CurrentClientIdProvider,
private val mlsClientProvider: MLSClientProvider,
private val userRepository: UserRepository,
private val dispatchers: KaliumDispatcher = KaliumDispatcherImpl
) : E2EClientProvider {
) : E2EIClientProvider {

private var e2EIClient: E2EIClient? = null

Expand All @@ -62,11 +63,21 @@ internal class E2EIClientProviderImpl(
} ?: run {
getSelfUserInfo().flatMap { selfUser ->
mlsClientProvider.getMLSClient(currentClientId).flatMap {
val newE2EIClient = it.newAcmeEnrollment(
e2eiClientId,
selfUser.first,
selfUser.second
)
val newE2EIClient = if (it.isE2EIEnabled()) {
kaliumLogger.e("initial E2EI client for MLS client without e2ei")
it.e2eiNewRotateEnrollment(
e2eiClientId,
selfUser.first,
selfUser.second
)
} else {
kaliumLogger.e("initial E2EI client for mls client that already has e2ei enabled")
it.e2eiNewActivationEnrollment(
e2eiClientId,
selfUser.first,
selfUser.second
)
}
e2EIClient = newE2EIClient
Either.Right(newE2EIClient)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import com.wire.kalium.cryptography.AcmeDirectory
import com.wire.kalium.cryptography.NewAcmeAuthz
import com.wire.kalium.cryptography.NewAcmeOrder
import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.data.client.E2EClientProvider
import com.wire.kalium.logic.data.client.E2EIClientProvider
import com.wire.kalium.logic.data.client.MLSClientProvider
import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.functional.Either
Expand Down Expand Up @@ -65,15 +65,15 @@ interface E2EIRepository {
class E2EIRepositoryImpl(
private val e2EIApi: E2EIApi,
private val acmeApi: ACMEApi,
private val e2EClientProvider: E2EClientProvider,
private val e2EIClientProvider: E2EIClientProvider,
private val mlsClientProvider: MLSClientProvider,
private val currentClientIdProvider: CurrentClientIdProvider
) : E2EIRepository {

override suspend fun loadACMEDirectories(): Either<CoreFailure, AcmeDirectory> = wrapApiRequest {
acmeApi.getACMEDirectories()
}.flatMap { directories ->
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
wrapE2EIRequest {
e2eiClient.directoryResponse(Json.encodeToString(directories).encodeToByteArray())
}
Expand All @@ -85,7 +85,7 @@ class E2EIRepositoryImpl(
}

override suspend fun createNewAccount(prevNonce: String, createAccountEndpoint: String) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val accountRequest = e2eiClient.getNewAccountRequest(prevNonce)
wrapApiRequest {
acmeApi.sendACMERequest(createAccountEndpoint, accountRequest)
Expand All @@ -96,7 +96,7 @@ class E2EIRepositoryImpl(
}

override suspend fun createNewOrder(prevNonce: String, createOrderEndpoint: String) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val orderRequest = e2eiClient.getNewOrderRequest(prevNonce)
wrapApiRequest {
acmeApi.sendACMERequest(createOrderEndpoint, orderRequest)
Expand All @@ -107,7 +107,7 @@ class E2EIRepositoryImpl(
}

override suspend fun createAuthz(prevNonce: String, authzEndpoint: String) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val authzRequest = e2eiClient.getNewAuthzRequest(authzEndpoint, prevNonce)
wrapApiRequest {
acmeApi.sendACMERequest(authzEndpoint, authzRequest)
Expand All @@ -129,12 +129,12 @@ class E2EIRepositoryImpl(
}
}

override suspend fun getDPoPToken(wireNonce: String) = e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
override suspend fun getDPoPToken(wireNonce: String) = e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
Either.Right(e2eiClient.createDpopToken(wireNonce))
}

override suspend fun validateDPoPChallenge(accessToken: String, prevNonce: String, acmeChallenge: AcmeChallenge) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val challengeRequest = e2eiClient.getNewDpopChallengeRequest(accessToken, prevNonce)
wrapApiRequest {
acmeApi.sendChallengeRequest(acmeChallenge.url, challengeRequest)
Expand All @@ -145,7 +145,7 @@ class E2EIRepositoryImpl(
}

override suspend fun validateOIDCChallenge(idToken: String, prevNonce: String, acmeChallenge: AcmeChallenge) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val challengeRequest = e2eiClient.getNewOidcChallengeRequest(idToken, prevNonce)
wrapApiRequest {
acmeApi.sendChallengeRequest(acmeChallenge.url, challengeRequest)
Expand All @@ -156,13 +156,13 @@ class E2EIRepositoryImpl(
}

override suspend fun validateChallenge(challengeResponse: ChallengeResponse) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2eiClient.setChallengeResponse(Json.encodeToString(challengeResponse).encodeToByteArray())
Either.Right(Unit)
}

override suspend fun checkOrderRequest(location: String, prevNonce: String) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val checkOrderRequest = e2eiClient.checkOrderRequest(location, prevNonce)
wrapApiRequest {
acmeApi.sendACMERequest(location, checkOrderRequest)
Expand All @@ -173,7 +173,7 @@ class E2EIRepositoryImpl(
}

override suspend fun finalize(location: String, prevNonce: String) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val finalizeRequest = e2eiClient.finalizeRequest(prevNonce)
wrapApiRequest {
acmeApi.sendACMERequest(location, finalizeRequest)
Expand All @@ -184,15 +184,15 @@ class E2EIRepositoryImpl(
}

override suspend fun certificateRequest(location: String, prevNonce: String) =
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
val certificateRequest = e2eiClient.certificateRequest(prevNonce)
wrapApiRequest {
acmeApi.sendACMERequest(location, certificateRequest)
}.map { it }
}

override suspend fun initMLSClientWithCertificate(certificateChain: String) {
e2EClientProvider.getE2EIClient().flatMap { e2eiClient ->
e2EIClientProvider.getE2EIClient().flatMap { e2eiClient ->
mlsClientProvider.getMLSClient().map {
it.e2eiMlsInitOnly(e2eiClient, certificateChain)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import kotlinx.serialization.json.Json
import kotlin.time.Duration.Companion.minutes

@Suppress("TooManyFunctions")
internal interface UserRepository {
interface UserRepository {
suspend fun fetchSelfUser(): Either<CoreFailure, Unit>

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ import com.wire.kalium.logic.data.call.VideoStateCheckerImpl
import com.wire.kalium.logic.data.call.mapper.CallMapper
import com.wire.kalium.logic.data.client.ClientDataSource
import com.wire.kalium.logic.data.client.ClientRepository
import com.wire.kalium.logic.data.client.E2EClientProvider
import com.wire.kalium.logic.data.client.E2EIClientProviderImpl
import com.wire.kalium.logic.data.client.E2EIClientProvider
import com.wire.kalium.logic.data.client.EI2EIClientProviderImpl
import com.wire.kalium.logic.data.client.MLSClientProvider
import com.wire.kalium.logic.data.client.MLSClientProviderImpl
import com.wire.kalium.logic.data.client.remote.ClientRemoteDataSource
Expand Down Expand Up @@ -595,8 +595,8 @@ class UserSessionScope internal constructor(
clientIdProvider
)

private val e2EIClientProvider: E2EClientProvider by lazy {
E2EIClientProviderImpl(
private val e2EIClientProvider: E2EIClientProvider by lazy {
EI2EIClientProviderImpl(
userId = userId,
currentClientIdProvider = clientIdProvider,
mlsClientProvider = mlsClientProvider,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program 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.
*
* This program 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 this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.client

import com.wire.kalium.logic.data.client.E2EIClientProvider
import com.wire.kalium.logic.data.client.EI2EIClientProviderImpl
import com.wire.kalium.logic.framework.TestClient
import com.wire.kalium.logic.framework.TestUser
import com.wire.kalium.logic.util.arrangement.provider.E2EIClientProviderArrangement
import com.wire.kalium.logic.util.arrangement.provider.E2EIClientProviderArrangementImpl
import com.wire.kalium.logic.util.shouldFail
import com.wire.kalium.logic.util.shouldSucceed
import io.mockative.any
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.test.runTest
import kotlin.test.Test

class E2EIClientProviderTest {
@Test
fun givenMLSClientWithoutE2EI_whenGettingE2EIClient_callsNewRotateEnrollment() = runTest{
val (arrangement, e2eiClientProvider) = Arrangement()
.arrange {
withGetMLSClientSuccessful()
withE2EINewActivationEnrollmentSuccessful()
withSelfUser(TestUser.SELF)
withE2EIEnabled(false)
}

e2eiClientProvider.getE2EIClient(TestClient.CLIENT_ID).shouldSucceed()

verify(arrangement.userRepository)
.suspendFunction(arrangement.userRepository::getSelfUser)
.wasInvoked(exactly = once)

verify(arrangement.mlsClient)
.suspendFunction(arrangement.mlsClient::e2eiNewActivationEnrollment)
.with(any(), any(), any())
.wasInvoked(exactly = once)

verify(arrangement.mlsClient)
.suspendFunction(arrangement.mlsClient::e2eiNewRotateEnrollment)
.with(any(),any(),any())
.wasNotInvoked()
}

@Test
fun givenMLSClientWithE2EI_whenGettingE2EIClient_callsNewActivationEnrollment() = runTest{
val (arrangement, e2eiClientProvider) = Arrangement()
.arrange {
withGetMLSClientSuccessful()
withE2EINewRotationEnrollmentSuccessful()
withSelfUser(TestUser.SELF)
withE2EIEnabled(true)
}

e2eiClientProvider.getE2EIClient(TestClient.CLIENT_ID).shouldSucceed()

verify(arrangement.userRepository)
.suspendFunction(arrangement.userRepository::getSelfUser)
.wasInvoked(exactly = once)

verify(arrangement.mlsClientProvider)
.suspendFunction(arrangement.mlsClientProvider::getMLSClient)
.with(any())
.wasInvoked(exactly = once)

verify(arrangement.mlsClient)
.suspendFunction(arrangement.mlsClient::e2eiNewRotateEnrollment)
.with(any(),any(),any())
.wasInvoked(exactly = once)

verify(arrangement.mlsClient)
.suspendFunction(arrangement.mlsClient::e2eiNewActivationEnrollment)
.with(any(), any(), any())
.wasNotInvoked()
}

@Test
fun givenSelfUserNotFound_whenGettingE2EIClient_ReturnsError() = runTest{
val (arrangement, e2eiClientProvider) = Arrangement()
.arrange {
withGetMLSClientSuccessful()
withE2EINewRotationEnrollmentSuccessful()
withSelfUser(null)
withE2EIEnabled(true)
}

e2eiClientProvider.getE2EIClient(TestClient.CLIENT_ID).shouldFail()

verify(arrangement.userRepository)
.suspendFunction(arrangement.userRepository::getSelfUser)
.wasInvoked(exactly = once)

verify(arrangement.mlsClientProvider)
.suspendFunction(arrangement.mlsClientProvider::getMLSClient)
.with(any())
.wasNotInvoked()

verify(arrangement.mlsClient)
.suspendFunction(arrangement.mlsClient::e2eiNewRotateEnrollment)
.with(any(),any(),any())
.wasNotInvoked()

verify(arrangement.mlsClient)
.suspendFunction(arrangement.mlsClient::e2eiNewActivationEnrollment)
.with(any(), any(), any())
.wasNotInvoked()
}

private class Arrangement :
E2EIClientProviderArrangement by E2EIClientProviderArrangementImpl() {
private lateinit var e2eiClientProvider: E2EIClientProvider

fun arrange(block: Arrangement.() -> Unit): Pair<Arrangement, E2EIClientProvider> {
apply(block)
e2eiClientProvider = EI2EIClientProviderImpl(
TestUser.USER_ID,
currentClientIdProvider,
mlsClientProvider,
userRepository
)

return this to e2eiClientProvider
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,28 @@
package com.wire.kalium.logic.data.e2ei

import com.wire.kalium.cryptography.*
import com.wire.kalium.cryptography.utils.generateRandomAES256Key
import com.wire.kalium.logic.data.client.E2EClientProvider
import com.wire.kalium.logic.data.client.E2EIClientProvider
import com.wire.kalium.logic.data.client.MLSClientProvider
import com.wire.kalium.logic.data.e2ei.E2EIRepositoryTest.Arrangement.Companion.ACME_CHALLENGE
import com.wire.kalium.logic.data.e2ei.E2EIRepositoryTest.Arrangement.Companion.ACME_DIRECTORIES
import com.wire.kalium.logic.data.e2ei.E2EIRepositoryTest.Arrangement.Companion.ACME_DIRECTORIES_RESPONSE
import com.wire.kalium.logic.data.e2ei.E2EIRepositoryTest.Arrangement.Companion.RANDOM_ACCESS_TOKEN
import com.wire.kalium.logic.data.e2ei.E2EIRepositoryTest.Arrangement.Companion.RANDOM_ID_TOKEN
import com.wire.kalium.logic.data.e2ei.E2EIRepositoryTest.Arrangement.Companion.RANDOM_NONCE
import com.wire.kalium.logic.data.e2ei.E2EIRepositoryTest.Arrangement.Companion.RANDOM_URL
import com.wire.kalium.logic.data.featureConfig.*
import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.util.shouldFail
import com.wire.kalium.logic.util.shouldSucceed
import com.wire.kalium.network.api.base.authenticated.e2ei.E2EIApi
import com.wire.kalium.network.api.base.authenticated.featureConfigs.*
import com.wire.kalium.network.api.base.model.ErrorResponse
import com.wire.kalium.network.api.base.unbound.acme.ACMEApi
import com.wire.kalium.network.api.base.unbound.acme.ACMEResponse
import com.wire.kalium.network.api.base.unbound.acme.AcmeDirectoriesResponse
import com.wire.kalium.network.api.base.unbound.acme.ChallengeResponse
import com.wire.kalium.network.exceptions.KaliumException
import com.wire.kalium.network.utils.NetworkResponse
import com.wire.kalium.util.serialization.toJsonElement
import io.ktor.util.*
import io.mockative.*
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlin.test.Test
import kotlin.test.assertEquals

class E2EIRepositoryTest {
@Test
Expand Down Expand Up @@ -768,7 +758,7 @@ class E2EIRepositoryTest {
val acmeApi: ACMEApi = mock(classOf<ACMEApi>())

@Mock
val e2eiClientProvider: E2EClientProvider = mock(classOf<E2EClientProvider>())
val e2eiClientProvider: E2EIClientProvider = mock(classOf<E2EIClientProvider>())

@Mock
val e2eiClient = mock(classOf<E2EIClient>())
Expand Down
Loading

0 comments on commit ed9dbde

Please sign in to comment.