Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add use case to check if backend supports personal to team migration (WPB-12022) #3114

Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import com.wire.kalium.util.KaliumDispatcherImpl
import io.ktor.http.Url
import kotlinx.coroutines.withContext

internal interface ServerConfigRepository {
interface ServerConfigRepository {
suspend fun getOrFetchMetadata(serverLinks: ServerConfig.Links): Either<CoreFailure, ServerConfig>
suspend fun storeConfig(links: ServerConfig.Links, metadata: ServerConfig.MetaData): Either<StorageFailure, ServerConfig>

Expand All @@ -62,6 +62,7 @@ internal interface ServerConfigRepository {
* Return the server links and metadata for the given userId
*/
suspend fun configForUser(userId: UserId): Either<StorageFailure, ServerConfig>
suspend fun commonApiVersion(domain: String): Either<CoreFailure, Int>
}

@Suppress("LongParameterList", "TooManyFunctions")
Expand Down Expand Up @@ -134,6 +135,10 @@ internal class ServerConfigDataSource(
wrapStorageRequest { dao.configForUser(userId.toDao()) }
.map { serverConfigMapper.fromEntity(it) }

override suspend fun commonApiVersion(domain: String): Either<CoreFailure, Int> = wrapStorageRequest {
dao.getCommonApiVersion(domain)
}

private suspend fun fetchMetadata(serverLinks: ServerConfig.Links): Either<CoreFailure, ServerConfig.MetaData> =
wrapApiRequest { versionApi.fetchApiVersion(Url(serverLinks.api)) }
.flatMap {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Wire
* Copyright (C) 2024 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.feature.personaltoteamaccount

import com.wire.kalium.logic.configuration.server.ServerConfigRepository
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.functional.fold

/**
* Use case to check if the backend supports personal to team account migration.
*/
interface IsPersonalToTeamAccountSupportedByBackendUseCase {
suspend operator fun invoke(): Boolean
}

class IsPersonalToTeamAccountSupportedByBackendUseCaseImpl(
val serverConfigRepository: ServerConfigRepository,
val userId: UserId
) : IsPersonalToTeamAccountSupportedByBackendUseCase {
override suspend fun invoke(): Boolean {
return serverConfigRepository.commonApiVersion(userId.domain).fold(
{ false },
{ it >= MIN_API_VERSION }
)
}

companion object {
const val MIN_API_VERSION = 7
ohassine marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ import com.wire.kalium.logic.feature.featureConfig.FeatureFlagSyncWorkerImpl
import com.wire.kalium.logic.feature.featureConfig.FeatureFlagsSyncWorker
import com.wire.kalium.logic.feature.featureConfig.SyncFeatureConfigsUseCase
import com.wire.kalium.logic.feature.message.MessageSender
import com.wire.kalium.logic.feature.personaltoteamaccount.IsPersonalToTeamAccountSupportedByBackendUseCase
import com.wire.kalium.logic.feature.personaltoteamaccount.IsPersonalToTeamAccountSupportedByBackendUseCaseImpl
import com.wire.kalium.logic.feature.publicuser.GetAllContactsUseCase
import com.wire.kalium.logic.feature.publicuser.GetAllContactsUseCaseImpl
import com.wire.kalium.logic.feature.publicuser.GetKnownUserUseCase
Expand Down Expand Up @@ -223,4 +225,9 @@ class UserScope internal constructor(
kaliumLogger = userScopedLogger,
)
}
val isPersonalToTeamAccountSupportedByBackend: IsPersonalToTeamAccountSupportedByBackendUseCase
get() = IsPersonalToTeamAccountSupportedByBackendUseCaseImpl(
serverConfigRepository = serverConfigRepository,
userId = selfUserId
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Wire
* Copyright (C) 2024 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.feature.personaltoteamaccount

import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.configuration.server.ServerConfigRepository
import com.wire.kalium.logic.framework.TestUser
import com.wire.kalium.logic.functional.Either
import io.mockative.Mock
import io.mockative.coEvery
import io.mockative.coVerify
import io.mockative.mock
import io.mockative.once
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class IsPersonalToTeamAccountSupportedByBackendUseCaseTest {

@Test
fun `given API version below minimum when invoking then returns false`() = runTest {
// Given
val (arrangement, useCase) = Arrangement()
.withRepositoryReturning(Either.Right(6))
.arrange()

// When
val result = useCase.invoke()

// Then
assertFalse(result)
coVerify {
arrangement.serverConfigRepository.commonApiVersion(TestUser.USER_ID.domain)
}.wasInvoked(once)
}

@Test
fun `given API version equal to minimum when invoking then returns true`() = runBlocking {
// Given
val (arrangement, useCase) = Arrangement()
.withRepositoryReturning(Either.Right(7))
.arrange()

// When
val result = useCase.invoke()

// Then
assertTrue(result)
coVerify {
arrangement.serverConfigRepository.commonApiVersion(TestUser.USER_ID.domain)
}.wasInvoked(once)
}

@Test
fun `given API version above minimum when invoking then returns true`() = runBlocking {
// Given
val (arrangement, useCase) = Arrangement()
.withRepositoryReturning(Either.Right(8))
.arrange()

// When
val result = useCase.invoke()

// Then
assertTrue(result)
coVerify {
arrangement.serverConfigRepository.commonApiVersion(TestUser.USER_ID.domain)
}.wasInvoked(once)
}

@Test
fun `given error fetching API version when invoking then returns false`() = runTest {
// Given
val (arrangement, useCase) = Arrangement()
.withRepositoryReturning(Either.Left(CoreFailure.SyncEventOrClientNotFound))
.arrange()

// When
val result = useCase.invoke()

// Then
assertFalse(result)
coVerify {
arrangement.serverConfigRepository.commonApiVersion(TestUser.USER_ID.domain)
}.wasInvoked(once)
}

private class Arrangement {

@Mock
val serverConfigRepository = mock(ServerConfigRepository::class)

suspend fun withRepositoryReturning(value: Either<CoreFailure, Int>) = apply {
coEvery {
serverConfigRepository.commonApiVersion(TestUser.USER_ID.domain)
}.returns(value)
}

fun arrange() = this to IsPersonalToTeamAccountSupportedByBackendUseCaseImpl(
serverConfigRepository = serverConfigRepository,
userId = TestUser.USER_ID
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ UPDATE ServerConfiguration SET commonApiVersion = ? WHERE id = ?;
updateApiVersionAndDomain:
UPDATE ServerConfiguration SET commonApiVersion = ?, domain = ? WHERE id = ?;

getCommonApiVersionByDomain:
SELECT commonApiVersion FROM ServerConfiguration WHERE domain = ?;

updateLastBlackListCheckByIds:
UPDATE ServerConfiguration SET lastBlackListCheck = ? WHERE id IN ?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ interface ServerConfigurationDAO {
fun configById(id: String): ServerConfigEntity?
suspend fun configByLinks(links: ServerConfigEntity.Links): ServerConfigEntity?
suspend fun updateApiVersion(id: String, commonApiVersion: Int)
suspend fun getCommonApiVersion(domain: String): Int
suspend fun updateApiVersionAndDomain(id: String, domain: String, commonApiVersion: Int)
suspend fun configForUser(userId: UserIDEntity): ServerConfigEntity?
suspend fun setFederationToTrue(id: String)
Expand Down Expand Up @@ -213,6 +214,10 @@ internal class ServerConfigurationDAOImpl internal constructor(
queries.updateApiVersion(commonApiVersion, id)
}

override suspend fun getCommonApiVersion(domain: String): Int = withContext(queriesContext) {
queries.getCommonApiVersionByDomain(domain).executeAsOne()
}

override suspend fun updateApiVersionAndDomain(id: String, domain: String, commonApiVersion: Int) =
withContext(queriesContext) {
queries.updateApiVersionAndDomain(commonApiVersion, domain, id)
Expand Down
Loading