diff --git a/android/src/main/kotlin/com/wire/kalium/presentation/MainActivity.kt b/android/src/main/kotlin/com/wire/kalium/presentation/MainActivity.kt index 773380becb4..cf8dbb79fd9 100644 --- a/android/src/main/kotlin/com/wire/kalium/presentation/MainActivity.kt +++ b/android/src/main/kotlin/com/wire/kalium/presentation/MainActivity.kt @@ -100,7 +100,7 @@ class MainActivity : ComponentActivity() { } private suspend fun provideAuthScope(coreLogic: CoreLogic, backendLinks: ServerConfig.Links): AuthenticationScope = - when (val result = coreLogic.versionedAuthenticationScope(backendLinks).invoke()) { + when (val result = coreLogic.versionedAuthenticationScope(backendLinks).invoke(null)) { is AutoVersionAuthScopeUseCase.Result.Failure.Generic -> error("Generic failure") AutoVersionAuthScopeUseCase.Result.Failure.TooNewVersion -> error("Too new version") AutoVersionAuthScopeUseCase.Result.Failure.UnknownServerVersion -> error("Unknown server version") diff --git a/cli/src/commonMain/kotlin/com/wire/kalium/cli/commands/LoginCommand.kt b/cli/src/commonMain/kotlin/com/wire/kalium/cli/commands/LoginCommand.kt index f409ed47fc5..b404e2bfa48 100644 --- a/cli/src/commonMain/kotlin/com/wire/kalium/cli/commands/LoginCommand.kt +++ b/cli/src/commonMain/kotlin/com/wire/kalium/cli/commands/LoginCommand.kt @@ -68,7 +68,8 @@ class LoginCommand : CliktCommand(name = "login") { } private suspend fun provideVersionedAuthenticationScope(serverLinks: ServerConfig.Links): AuthenticationScope = - when (val result = coreLogic.versionedAuthenticationScope(serverLinks).invoke()) { + // CLI does not support proxy mode so we can pass null here + when (val result = coreLogic.versionedAuthenticationScope(serverLinks).invoke(null)) { is AutoVersionAuthScopeUseCase.Result.Failure.Generic -> throw PrintMessage("failed to create authentication scope: ${result.genericFailure}") diff --git a/logic/src/androidMain/kotlin/com/wire/kalium/logic/CoreLogic.kt b/logic/src/androidMain/kotlin/com/wire/kalium/logic/CoreLogic.kt index aa126e2bc21..80514fa7ca1 100644 --- a/logic/src/androidMain/kotlin/com/wire/kalium/logic/CoreLogic.kt +++ b/logic/src/androidMain/kotlin/com/wire/kalium/logic/CoreLogic.kt @@ -25,12 +25,12 @@ import com.wire.kalium.logic.feature.UserSessionScopeProvider import com.wire.kalium.logic.feature.UserSessionScopeProviderImpl import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs -import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.logic.network.NetworkStateObserverImpl import com.wire.kalium.logic.sync.GlobalWorkScheduler import com.wire.kalium.logic.sync.GlobalWorkSchedulerImpl import com.wire.kalium.logic.util.PlatformContext import com.wire.kalium.logic.util.SecurityHelperImpl +import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider import kotlinx.coroutines.cancel @@ -83,6 +83,7 @@ actual class CoreLogic( rootPathsProvider, appContext, getGlobalScope(), + globalDatabase, kaliumConfigs, globalPreferences, globalCallManager, diff --git a/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt b/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt index 85091ccc8b7..5d45b410879 100644 --- a/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt +++ b/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt @@ -32,9 +32,10 @@ import com.wire.kalium.logic.feature.auth.AuthenticationScopeProvider import com.wire.kalium.logic.feature.auth.LogoutCallback import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs -import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.logic.sync.UserSessionWorkScheduler import com.wire.kalium.logic.util.SecurityHelperImpl +import com.wire.kalium.network.NetworkStateObserver +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider @Suppress("LongParameterList") @@ -43,6 +44,7 @@ internal fun UserSessionScope( userAgent: String, userId: UserId, globalScope: GlobalKaliumScope, + globalDatabaseProvider: GlobalDatabaseProvider, globalCallManager: GlobalCallManager, globalPreferences: GlobalPrefProvider, authenticationScopeProvider: AuthenticationScopeProvider, @@ -65,6 +67,7 @@ internal fun UserSessionScope( userId, globalScope, globalCallManager, + globalDatabaseProvider, globalPreferences, authenticationScopeProvider, userSessionWorkScheduler, diff --git a/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt b/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt index aaa79cfb800..853f122677f 100644 --- a/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt +++ b/logic/src/androidMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt @@ -33,8 +33,9 @@ import com.wire.kalium.logic.feature.auth.AuthenticationScopeProvider import com.wire.kalium.logic.feature.auth.LogoutCallback import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs -import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.logic.sync.UserSessionWorkSchedulerImpl +import com.wire.kalium.network.NetworkStateObserver +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider import com.wire.kalium.persistence.util.FileNameUtil @@ -44,6 +45,7 @@ internal actual class UserSessionScopeProviderImpl( private val rootPathsProvider: RootPathsProvider, private val appContext: Context, private val globalScope: GlobalKaliumScope, + private val globalDatabaseProvider: GlobalDatabaseProvider, private val kaliumConfigs: KaliumConfigs, private val globalPreferences: GlobalPrefProvider, private val globalCallManager: GlobalCallManager, @@ -67,6 +69,7 @@ internal actual class UserSessionScopeProviderImpl( globalScope = globalScope, globalCallManager = globalCallManager, globalPreferences = globalPreferences, + globalDatabaseProvider = globalDatabaseProvider, authenticationScopeProvider = authenticationScopeProvider, userSessionWorkScheduler = userSessionWorkScheduler, rootPathsProvider = rootPathsProvider, diff --git a/logic/src/appleMain/kotlin/com/wire/kalium/logic/CoreLogic.kt b/logic/src/appleMain/kotlin/com/wire/kalium/logic/CoreLogic.kt index be152506e2e..0c2e0cec031 100644 --- a/logic/src/appleMain/kotlin/com/wire/kalium/logic/CoreLogic.kt +++ b/logic/src/appleMain/kotlin/com/wire/kalium/logic/CoreLogic.kt @@ -57,6 +57,7 @@ actual class CoreLogic( kaliumConfigs, globalPreferences, globalCallManager, + globalDatabase, userStorageProvider, networkStateObserver, logoutCallbackManager, diff --git a/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt b/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt index 026d18bd1ec..b9fb470fa6c 100644 --- a/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt +++ b/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt @@ -33,6 +33,7 @@ import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.logic.sync.UserSessionWorkScheduler +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider @Suppress("LongParameterList") @@ -42,6 +43,7 @@ internal fun UserSessionScope( globalScope: GlobalKaliumScope, globalCallManager: GlobalCallManager, globalPreferences: GlobalPrefProvider, + globalDatabaseProvider: GlobalDatabaseProvider, authenticationScopeProvider: AuthenticationScopeProvider, userSessionWorkScheduler: UserSessionWorkScheduler, rootPathsProvider: RootPathsProvider, @@ -61,6 +63,7 @@ internal fun UserSessionScope( userId, globalScope, globalCallManager, + globalDatabaseProvider, globalPreferences, authenticationScopeProvider, userSessionWorkScheduler, diff --git a/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt b/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt index 653bd4e90a6..d586073047b 100644 --- a/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt +++ b/logic/src/appleMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt @@ -34,6 +34,7 @@ import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.logic.sync.UserSessionWorkSchedulerImpl +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider @Suppress("LongParameterList") @@ -44,6 +45,7 @@ internal actual class UserSessionScopeProviderImpl( private val kaliumConfigs: KaliumConfigs, private val globalPreferences: GlobalPrefProvider, private val globalCallManager: GlobalCallManager, + private val globalDatabaseProvider: GlobalDatabaseProvider, private val userStorageProvider: UserStorageProvider, private val networkStateObserver: NetworkStateObserver, private val logoutCallback: LogoutCallback, @@ -63,6 +65,7 @@ internal actual class UserSessionScopeProviderImpl( globalScope, globalCallManager, globalPreferences, + globalDatabaseProvider, authenticationScopeProvider, userSessionWorkScheduler, rootPathsProvider, diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/CoreLogic.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/CoreLogic.kt index a06df775e33..f3b1934e10d 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/CoreLogic.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/CoreLogic.kt @@ -50,7 +50,7 @@ abstract class CoreLogicCommon internal constructor( protected val idMapper: IdMapper = MapperProvider.idMapper() ) { protected abstract val globalPreferences: GlobalPrefProvider - protected abstract val globalDatabase: GlobalDatabaseProvider + internal abstract val globalDatabase: GlobalDatabaseProvider protected abstract val userSessionScopeProvider: Lazy protected val userStorageProvider: UserStorageProvider = PlatformUserStorageProvider() @@ -75,15 +75,14 @@ abstract class CoreLogicCommon internal constructor( @Suppress("MemberVisibilityCanBePrivate") // Can be used by other targets like iOS and JS fun getAuthenticationScope( serverConfig: ServerConfig, - proxyCredentials: ProxyCredentials? = null + proxyCredentials: ProxyCredentials? ): AuthenticationScope = authenticationScopeProvider.provide( serverConfig, proxyCredentials, - getGlobalScope().serverConfigRepository, networkStateObserver, - kaliumConfigs::certPinningConfig, - kaliumConfigs.kaliumMockEngine?.mockEngine + globalDatabase, + kaliumConfigs ) @Suppress("MemberVisibilityCanBePrivate") // Can be used by other targets like iOS and JS @@ -94,8 +93,12 @@ abstract class CoreLogicCommon internal constructor( // TODO: make globalScope a singleton inline fun globalScope(action: GlobalKaliumScope.() -> T): T = getGlobalScope().action() - inline fun authenticationScope(serverConfig: ServerConfig, action: AuthenticationScope.() -> T): T = - getAuthenticationScope(serverConfig).action() + inline fun authenticationScope( + serverConfig: ServerConfig, + proxyCredentials: ProxyCredentials?, + action: AuthenticationScope.() -> T + ): T = + getAuthenticationScope(serverConfig, proxyCredentials).action() inline fun sessionScope( userId: UserId, diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/GlobalKaliumScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/GlobalKaliumScope.kt index d2f789874e1..0b1b28cdfea 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/GlobalKaliumScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/GlobalKaliumScope.kt @@ -20,8 +20,8 @@ package com.wire.kalium.logic import com.wire.kalium.logic.configuration.notification.NotificationTokenDataSource import com.wire.kalium.logic.configuration.notification.NotificationTokenRepository -import com.wire.kalium.logic.configuration.server.ServerConfigDataSource -import com.wire.kalium.logic.configuration.server.ServerConfigRepository +import com.wire.kalium.logic.configuration.server.CustomServerConfigDataSource +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.data.client.UserClientRepositoryProvider import com.wire.kalium.logic.data.client.UserClientRepositoryProviderImpl import com.wire.kalium.logic.data.session.SessionDataSource @@ -49,10 +49,7 @@ import com.wire.kalium.logic.feature.notificationToken.SaveNotificationTokenUseC import com.wire.kalium.logic.feature.rootDetection.CheckSystemIntegrityUseCase import com.wire.kalium.logic.feature.rootDetection.CheckSystemIntegrityUseCaseImpl import com.wire.kalium.logic.feature.rootDetection.RootDetectorImpl -import com.wire.kalium.logic.feature.server.FetchApiVersionUseCase -import com.wire.kalium.logic.feature.server.FetchApiVersionUseCaseImpl import com.wire.kalium.logic.feature.server.GetServerConfigUseCase -import com.wire.kalium.logic.feature.server.ObserveServerConfigUseCase import com.wire.kalium.logic.feature.server.ServerConfigForAccountUseCase import com.wire.kalium.logic.feature.server.StoreServerConfigUseCase import com.wire.kalium.logic.feature.server.StoreServerConfigUseCaseImpl @@ -102,27 +99,17 @@ class GlobalKaliumScope internal constructor( val unboundNetworkContainer: UnboundNetworkContainer by lazy { UnboundNetworkContainerCommon( networkStateObserver, - kaliumConfigs.developmentApiEnabled, userAgent, - kaliumConfigs.ignoreSSLCertificatesForUnboundCalls, kaliumConfigs.certPinningConfig, kaliumConfigs.kaliumMockEngine?.mockEngine ) } - internal val serverConfigRepository: ServerConfigRepository - get() = ServerConfigDataSource( - unboundNetworkContainer.serverConfigApi, - globalDatabase.serverConfigurationDAO, - unboundNetworkContainer.remoteVersion, - kaliumConfigs.developmentApiEnabled - ) - val sessionRepository: SessionRepository get() = SessionDataSource( globalDatabase.accountsDAO, globalPreferences.authTokenStorage, - serverConfigRepository, + globalDatabase.serverConfigurationDAO, kaliumConfigs ) @@ -133,24 +120,41 @@ class GlobalKaliumScope internal constructor( get() = NotificationTokenDataSource(globalPreferences.tokenStorage) + private val customServerConfigRepository: CustomServerConfigRepository + get() = CustomServerConfigDataSource( + unboundNetworkContainer.serverConfigApi, + developmentApiEnabled = kaliumConfigs.developmentApiEnabled, + globalDatabase.serverConfigurationDAO + ) val validateEmailUseCase: ValidateEmailUseCase get() = ValidateEmailUseCaseImpl() val validateUserHandleUseCase: ValidateUserHandleUseCase get() = ValidateUserHandleUseCaseImpl() val validatePasswordUseCase: ValidatePasswordUseCase get() = ValidatePasswordUseCaseImpl() val addAuthenticatedAccount: AddAuthenticatedUserUseCase get() = - AddAuthenticatedUserUseCase(sessionRepository, serverConfigRepository) + AddAuthenticatedUserUseCase(sessionRepository, globalDatabase.serverConfigurationDAO) val getSessions: GetSessionsUseCase get() = GetSessionsUseCase(sessionRepository) val doesValidSessionExist: DoesValidSessionExistUseCase get() = DoesValidSessionExistUseCase(sessionRepository) val observeValidAccounts: ObserveValidAccountsUseCase get() = ObserveValidAccountsUseCaseImpl(sessionRepository, userSessionScopeProvider.value) val session: SessionScope get() = SessionScope(sessionRepository) - val fetchServerConfigFromDeepLink: GetServerConfigUseCase get() = GetServerConfigUseCase(serverConfigRepository) - val fetchApiVersion: FetchApiVersionUseCase get() = FetchApiVersionUseCaseImpl(serverConfigRepository) - val observeServerConfig: ObserveServerConfigUseCase get() = ObserveServerConfigUseCase(serverConfigRepository) - val updateApiVersions: UpdateApiVersionsUseCase get() = UpdateApiVersionsUseCaseImpl(serverConfigRepository) - val storeServerConfig: StoreServerConfigUseCase get() = StoreServerConfigUseCaseImpl(serverConfigRepository) + val fetchServerConfigFromDeepLink: GetServerConfigUseCase get() = GetServerConfigUseCase(customServerConfigRepository) + val updateApiVersions: UpdateApiVersionsUseCase + get() = UpdateApiVersionsUseCaseImpl( + sessionRepository, + globalPreferences.authTokenStorage, + { serverConfig, proxyCredentials -> + authenticationScopeProvider.provide( + serverConfig, + proxyCredentials, + networkStateObserver, + globalDatabase = globalDatabase, + kaliumConfigs = kaliumConfigs, + ).serverConfigRepository + }, + ) + val storeServerConfig: StoreServerConfigUseCase get() = StoreServerConfigUseCaseImpl(customServerConfigRepository) val saveNotificationToken: SaveNotificationTokenUseCase get() = SaveNotificationTokenUseCaseImpl( @@ -163,15 +167,15 @@ class GlobalKaliumScope internal constructor( get() = DeleteSessionUseCase(sessionRepository, userSessionScopeProvider.value) val serverConfigForAccounts: ServerConfigForAccountUseCase - get() = - ServerConfigForAccountUseCase(serverConfigRepository) + get() = ServerConfigForAccountUseCase(globalDatabase.serverConfigurationDAO) val observeIfAppUpdateRequired: ObserveIfAppUpdateRequiredUseCase get() = ObserveIfAppUpdateRequiredUseCaseImpl( - serverConfigRepository, + customServerConfigRepository, authenticationScopeProvider, userSessionScopeProvider.value, networkStateObserver, + globalDatabase, kaliumConfigs ) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/CustomServerConfigRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/CustomServerConfigRepository.kt new file mode 100644 index 00000000000..85c7d59dec2 --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/CustomServerConfigRepository.kt @@ -0,0 +1,134 @@ +/* + * 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.configuration.server + +import com.benasher44.uuid.uuid4 +import com.wire.kalium.logic.NetworkFailure +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.di.MapperProvider +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.functional.flatMap +import com.wire.kalium.logic.functional.map +import com.wire.kalium.logic.wrapApiRequest +import com.wire.kalium.logic.wrapStorageRequest +import com.wire.kalium.network.BackendMetaDataUtil +import com.wire.kalium.network.BackendMetaDataUtilImpl +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.api.base.unbound.versioning.VersionInfoDTO +import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +internal interface CustomServerConfigRepository { + /** + * download an on premise server configuration from a json file + * @param serverConfigUrl url for the server configuration url + * @return Either ServerConfigResponse or NetworkFailure + */ + suspend fun fetchRemoteConfig(serverConfigUrl: String): Either + suspend fun storeConfig(links: ServerConfig.Links, metadata: ServerConfig.MetaData): Either + + suspend fun storeConfig(links: ServerConfig.Links, versionInfo: ServerConfig.VersionInfo): Either + + /** + * @return the list of [ServerConfigWithUserId] that were checked "if app needs to be updated" after the date + */ + suspend fun getServerConfigsWithUserIdAfterTheDate(date: String): Either>> + + /** + * updates lastBlackListCheckDate for the Set of configIds + */ + suspend fun updateAppBlackListCheckDate(configIds: Set, date: String) +} + +internal class CustomServerConfigDataSource internal constructor( + private val api: ServerConfigApi, + private val developmentApiEnabled: Boolean, + private val serverConfigurationDAO: ServerConfigurationDAO, + private val backendMetaDataUtil: BackendMetaDataUtil = BackendMetaDataUtilImpl, + private val serverConfigMapper: ServerConfigMapper = MapperProvider.serverConfigMapper() +) : CustomServerConfigRepository { + + override suspend fun fetchRemoteConfig(serverConfigUrl: String): Either = + wrapApiRequest { api.fetchServerConfig(serverConfigUrl) } + .map { serverConfigMapper.fromDTO(it) } + + override suspend fun storeConfig( + links: ServerConfig.Links, + versionInfo: ServerConfig.VersionInfo + ): Either { + val metaDataDTO = backendMetaDataUtil.calculateApiVersion( + versionInfoDTO = VersionInfoDTO( + developmentSupported = versionInfo.developmentSupported, + domain = versionInfo.domain, + federation = versionInfo.federation, + supported = versionInfo.supported, + ), + developmentApiEnabled = developmentApiEnabled + ) + return storeConfig(links, serverConfigMapper.fromDTO(metaDataDTO)) + } + + override suspend fun storeConfig(links: ServerConfig.Links, metadata: ServerConfig.MetaData): Either = + wrapStorageRequest { + // check if such config is already inserted + val storedConfigId = serverConfigurationDAO.configByLinks(serverConfigMapper.toEntity(links))?.id + if (storedConfigId != null) { + // if already exists then just update it + serverConfigurationDAO.updateApiVersion(storedConfigId, metadata.commonApiVersion.version) + if (metadata.federation) serverConfigurationDAO.setFederationToTrue(storedConfigId) + storedConfigId + } else { + // otherwise insert new config + val newId = uuid4().toString() + serverConfigurationDAO.insert( + ServerConfigurationDAO.InsertData( + id = newId, + apiBaseUrl = links.api, + accountBaseUrl = links.accounts, + webSocketBaseUrl = links.webSocket, + blackListUrl = links.blackList, + teamsUrl = links.teams, + websiteUrl = links.website, + isOnPremises = links.isOnPremises, + title = links.title, + federation = metadata.federation, + domain = metadata.domain, + commonApiVersion = metadata.commonApiVersion.version, + apiProxyHost = links.apiProxy?.host, + apiProxyNeedsAuthentication = links.apiProxy?.needsAuthentication, + apiProxyPort = links.apiProxy?.port + ) + ) + newId + } + }.flatMap { storedConfigId -> + wrapStorageRequest { serverConfigurationDAO.configById(storedConfigId) } + }.map { + serverConfigMapper.fromEntity(it) + } + + override suspend fun getServerConfigsWithUserIdAfterTheDate(date: String): Either>> = + wrapStorageRequest { serverConfigurationDAO.getServerConfigsWithAccIdWithLastCheckBeforeDate(date) } + .map { it.map { list -> list.map(serverConfigMapper::fromEntity) } } + + override suspend fun updateAppBlackListCheckDate(configIds: Set, date: String) { + wrapStorageRequest { serverConfigurationDAO.updateBlackListCheckDate(configIds, date) } + } + +} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfig.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfig.kt index 33210252795..393a9b4976c 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfig.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfig.kt @@ -20,7 +20,6 @@ package com.wire.kalium.logic.configuration.server -import com.wire.kalium.logic.data.id.IdMapper import com.wire.kalium.logic.data.id.toModel import com.wire.kalium.logic.data.user.UserId import com.wire.kalium.network.tools.ApiVersionDTO @@ -163,8 +162,7 @@ interface ServerConfigMapper { } class ServerConfigMapperImpl( - private val apiVersionMapper: ApiVersionMapper, - private val idMapper: IdMapper + private val apiVersionMapper: ApiVersionMapper ) : ServerConfigMapper { override fun toDTO(serverConfig: ServerConfig): ServerConfigDTO = with(serverConfig) { ServerConfigDTO( diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt index dc0072240e3..ffde0908a40 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt @@ -20,7 +20,6 @@ package com.wire.kalium.logic.configuration.server import com.benasher44.uuid.uuid4 import com.wire.kalium.logic.CoreFailure -import com.wire.kalium.logic.NetworkFailure import com.wire.kalium.logic.StorageFailure import com.wire.kalium.logic.data.id.toDao import com.wire.kalium.logic.data.user.UserId @@ -32,47 +31,17 @@ import com.wire.kalium.logic.functional.fold import com.wire.kalium.logic.functional.map import com.wire.kalium.logic.wrapApiRequest import com.wire.kalium.logic.wrapStorageRequest -import com.wire.kalium.network.BackendMetaDataUtil -import com.wire.kalium.network.BackendMetaDataUtilImpl -import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi import com.wire.kalium.network.api.base.unbound.versioning.VersionApi -import com.wire.kalium.network.api.base.unbound.versioning.VersionInfoDTO import com.wire.kalium.network.tools.ApiVersionDTO import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO import com.wire.kalium.util.KaliumDispatcher import com.wire.kalium.util.KaliumDispatcherImpl import io.ktor.http.Url -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext -@Suppress("TooManyFunctions") internal interface ServerConfigRepository { - /** - * download an on premise server configuration from a json file - * @param serverConfigUrl url for the server configuration url - * @return Either ServerConfigResponse or NetworkFailure - */ - suspend fun fetchRemoteConfig(serverConfigUrl: String): Either - - /** - * @return list of all locally stored server configurations - */ - suspend fun configList(): Either> - - /** - * @return observable list of all locally stored server configurations - */ - suspend fun configFlow(): Either>> - - /** - * delete a locally stored server configuration - */ - suspend fun deleteById(id: String): Either - suspend fun delete(serverConfig: ServerConfig): Either suspend fun getOrFetchMetadata(serverLinks: ServerConfig.Links): Either suspend fun storeConfig(links: ServerConfig.Links, metadata: ServerConfig.MetaData): Either - suspend fun storeConfig(links: ServerConfig.Links, versionInfo: ServerConfig.VersionInfo): Either /** * calculate the app/server common api version for a new non stored config and store it locally if the version is valid @@ -84,61 +53,25 @@ internal interface ServerConfigRepository { */ suspend fun fetchApiVersionAndStore(links: ServerConfig.Links): Either - /** - * retrieve a config from the local DB by ID - */ - fun configById(id: String): Either - - /** - * retrieve a config from the local DB by Links - */ - suspend fun configByLinks(links: ServerConfig.Links): Either - /** * update the api version of a locally stored config */ - suspend fun updateConfigApiVersion(id: String): Either + suspend fun updateConfigApiVersion(serverConfig: ServerConfig): Either /** * Return the server links and metadata for the given userId */ suspend fun configForUser(userId: UserId): Either - - /** - * @return the list of [ServerConfigWithUserId] that were checked "if app needs to be updated" after the date - */ - suspend fun getServerConfigsWithUserIdAfterTheDate(date: String): Either>> - - /** - * updates lastBlackListCheckDate for the Set of configIds - */ - suspend fun updateAppBlackListCheckDate(configIds: Set, date: String) } @Suppress("LongParameterList", "TooManyFunctions") internal class ServerConfigDataSource( - private val api: ServerConfigApi, private val dao: ServerConfigurationDAO, private val versionApi: VersionApi, - private val developmentApiEnabled: Boolean, - private val backendMetaDataUtil: BackendMetaDataUtil = BackendMetaDataUtilImpl, private val serverConfigMapper: ServerConfigMapper = MapperProvider.serverConfigMapper(), private val dispatchers: KaliumDispatcher = KaliumDispatcherImpl ) : ServerConfigRepository { - override suspend fun fetchRemoteConfig(serverConfigUrl: String): Either = - wrapApiRequest { api.fetchServerConfig(serverConfigUrl) } - .map { serverConfigMapper.fromDTO(it) } - - override suspend fun configList(): Either> = - wrapStorageRequest { dao.allConfig() }.map { it.map(serverConfigMapper::fromEntity) } - - override suspend fun configFlow(): Either>> = - wrapStorageRequest { dao.allConfigFlow().map { it.map(serverConfigMapper::fromEntity) } } - - override suspend fun deleteById(id: String) = wrapStorageRequest { dao.deleteById(id) } - - override suspend fun delete(serverConfig: ServerConfig) = deleteById(serverConfig.id) override suspend fun getOrFetchMetadata(serverLinks: ServerConfig.Links): Either = wrapStorageRequest { dao.configByLinks(serverConfigMapper.toEntity(serverLinks)) }.fold({ fetchApiVersionAndStore(serverLinks) @@ -187,51 +120,20 @@ internal class ServerConfigDataSource( } } - override suspend fun storeConfig( - links: ServerConfig.Links, - versionInfo: ServerConfig.VersionInfo - ): Either { - val metaDataDTO = backendMetaDataUtil.calculateApiVersion( - versionInfoDTO = VersionInfoDTO( - developmentSupported = versionInfo.developmentSupported, - domain = versionInfo.domain, - federation = versionInfo.federation, - supported = versionInfo.supported, - ), - developmentApiEnabled = developmentApiEnabled - ) - return storeConfig(links, serverConfigMapper.fromDTO(metaDataDTO)) - } - override suspend fun fetchApiVersionAndStore(links: ServerConfig.Links): Either = fetchMetadata(links) .flatMap { metaData -> storeConfig(links, metaData) } - override fun configById(id: String): Either = wrapStorageRequest { - dao.configById(id) - }.map { serverConfigMapper.fromEntity(it) } - - override suspend fun configByLinks(links: ServerConfig.Links): Either = - wrapStorageRequest { dao.configByLinks(serverConfigMapper.toEntity(links)) }.map { serverConfigMapper.fromEntity(it) } - - override suspend fun updateConfigApiVersion(id: String): Either = configById(id) - .flatMap { fetchMetadata(it.links) } - .flatMap { wrapStorageRequest { dao.updateApiVersion(id, it.commonApiVersion.version) } } + override suspend fun updateConfigApiVersion(serverConfig: ServerConfig): Either = + fetchMetadata(serverConfig.links) + .flatMap { wrapStorageRequest { dao.updateApiVersion(serverConfig.id, it.commonApiVersion.version) } } override suspend fun configForUser(userId: UserId): Either = wrapStorageRequest { dao.configForUser(userId.toDao()) } .map { serverConfigMapper.fromEntity(it) } - override suspend fun getServerConfigsWithUserIdAfterTheDate(date: String): Either>> = - wrapStorageRequest { dao.getServerConfigsWithAccIdWithLastCheckBeforeDate(date) } - .map { it.map { list -> list.map(serverConfigMapper::fromEntity) } } - - override suspend fun updateAppBlackListCheckDate(configIds: Set, date: String) { - wrapStorageRequest { dao.updateBlackListCheckDate(configIds, date) } - } - private suspend fun fetchMetadata(serverLinks: ServerConfig.Links): Either = wrapApiRequest { versionApi.fetchApiVersion(Url(serverLinks.api)) } .flatMap { diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionMapper.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionMapper.kt index 56e2d30f88f..0a065d4cdba 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionMapper.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionMapper.kt @@ -19,7 +19,6 @@ package com.wire.kalium.logic.data.session import com.wire.kalium.logic.data.auth.login.ProxyCredentials -import com.wire.kalium.logic.data.id.IdMapper import com.wire.kalium.logic.data.id.toApi import com.wire.kalium.logic.data.id.toDao import com.wire.kalium.logic.data.id.toModel @@ -49,18 +48,18 @@ interface SessionMapper { fun fromSsoIdEntity(ssoIdEntity: SsoIdEntity?): SsoId? fun toLogoutReason(reason: LogoutReasonEntity): LogoutReason fun fromEntityToProxyCredentialsDTO(proxyCredentialsEntity: ProxyCredentialsEntity): ProxyCredentialsDTO + fun formEntityToProxyModel(proxyCredentialsEntity: ProxyCredentialsEntity): ProxyCredentials fun fromPersistentWebSocketStatusEntity( persistentWebSocketStatusEntity: PersistentWebSocketStatusEntity ): PersistentWebSocketStatus + fun fromModelToProxyCredentialsEntity(proxyCredentialsModel: ProxyCredentials): ProxyCredentialsEntity fun fromModelToProxyCredentialsDTO(proxyCredentialsModel: ProxyCredentials): ProxyCredentialsDTO fun fromDTOToProxyCredentialsModel(proxyCredentialsDTO: ProxyCredentialsDTO?): ProxyCredentials? } @Suppress("TooManyFunctions") -internal class SessionMapperImpl( - private val idMapper: IdMapper -) : SessionMapper { +internal class SessionMapperImpl : SessionMapper { override fun toSessionDTO(authSession: AccountTokens): SessionDTO = with(authSession) { SessionDTO( @@ -137,12 +136,19 @@ internal class SessionMapperImpl( override fun fromEntityToProxyCredentialsDTO(proxyCredentialsEntity: ProxyCredentialsEntity): ProxyCredentialsDTO = ProxyCredentialsDTO(proxyCredentialsEntity.username, proxyCredentialsEntity.password) + override fun formEntityToProxyModel(proxyCredentialsEntity: ProxyCredentialsEntity): ProxyCredentials = + ProxyCredentials( + username = proxyCredentialsEntity.username, + password = proxyCredentialsEntity.password + ) + override fun fromPersistentWebSocketStatusEntity( persistentWebSocketStatusEntity: PersistentWebSocketStatusEntity ): PersistentWebSocketStatus = PersistentWebSocketStatus( persistentWebSocketStatusEntity.userIDEntity.toModel(), persistentWebSocketStatusEntity.isPersistentWebSocketEnabled ) + override fun fromModelToProxyCredentialsEntity(proxyCredentialsModel: ProxyCredentials): ProxyCredentialsEntity = ProxyCredentialsEntity(proxyCredentialsModel.username, proxyCredentialsModel.password) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionRepository.kt index 4d264cd8101..ca54ba063bf 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/session/SessionRepository.kt @@ -20,7 +20,7 @@ package com.wire.kalium.logic.data.session import com.wire.kalium.logic.StorageFailure import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository +import com.wire.kalium.logic.configuration.server.ServerConfigMapper import com.wire.kalium.logic.data.auth.Account import com.wire.kalium.logic.data.auth.AccountInfo import com.wire.kalium.logic.data.auth.AccountTokens @@ -36,7 +36,7 @@ import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.featureFlags.KaliumConfigs 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.functional.getOrElse import com.wire.kalium.logic.functional.map import com.wire.kalium.logic.functional.onSuccess import com.wire.kalium.logic.wrapStorageNullableRequest @@ -45,6 +45,7 @@ import com.wire.kalium.network.api.base.model.ManagedByDTO import com.wire.kalium.persistence.client.AuthTokenStorage import com.wire.kalium.persistence.dao.ManagedByEntity import com.wire.kalium.persistence.daokaliumdb.AccountsDAO +import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO import com.wire.kalium.persistence.model.SsoIdEntity import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -61,7 +62,7 @@ interface SessionRepository { suspend fun allSessions(): Either> suspend fun allSessionsFlow(): Flow> suspend fun allValidSessions(): Either> - fun allValidSessionsFlow(): Flow>> + suspend fun allValidSessionsFlow(): Flow>> suspend fun doesValidSessionExist(userId: UserId): Either fun fullAccountInfo(userId: UserId): Either suspend fun userAccountInfo(userId: UserId): Either @@ -78,14 +79,16 @@ interface SessionRepository { suspend fun persistentWebSocketStatus(userId: UserId): Either suspend fun cookieLabel(userId: UserId): Either suspend fun isAccountReadOnly(userId: UserId): Either + suspend fun validSessionsWithServerConfig(): Either> } -@Suppress("TooManyFunctions") +@Suppress("TooManyFunctions", "LongParameterList") internal class SessionDataSource internal constructor( private val accountsDAO: AccountsDAO, private val authTokenStorage: AuthTokenStorage, - private val serverConfigRepository: ServerConfigRepository, + private val serverConfigDAO: ServerConfigurationDAO, private val kaliumConfigs: KaliumConfigs, + private val serverConfigMapper: ServerConfigMapper = MapperProvider.serverConfigMapper(), private val sessionMapper: SessionMapper = MapperProvider.sessionMapper(), private val idMapper: IdMapper = MapperProvider.idMapper() ) : SessionRepository { @@ -123,7 +126,7 @@ internal class SessionDataSource internal constructor( wrapStorageRequest { accountsDAO.allValidAccountList() } .map { it.map { AccountInfo.Valid(it.userIDEntity.toModel()) } } - override fun allValidSessionsFlow(): Flow>> = + override suspend fun allValidSessionsFlow(): Flow>> = accountsDAO.observerValidAccountList() .map { it.map { AccountInfo.Valid(it.userIDEntity.toModel()) } } .wrapStorageRequest() @@ -135,8 +138,11 @@ internal class SessionDataSource internal constructor( wrapStorageRequest { accountsDAO.fullAccountInfo(userId.toDao()) } .flatMap { val accountInfo = sessionMapper.fromAccountInfoEntity(it.info) - val serverConfig: ServerConfig = - serverConfigRepository.configById(it.serverConfigId).fold({ return Either.Left(it) }, { it }) + val serverConfig: ServerConfig = wrapStorageRequest { + serverConfigDAO.configById(it.serverConfigId) + }.map { serverConfigMapper.fromEntity(it) } + .getOrElse { return Either.Left(it) } + val ssoId: SsoId? = sessionMapper.fromSsoIdEntity(it.ssoId) Either.Right(Account(accountInfo, serverConfig, ssoId)) } @@ -225,6 +231,14 @@ internal class SessionDataSource internal constructor( } } + override suspend fun validSessionsWithServerConfig(): Either> = wrapStorageRequest { + accountsDAO.validAccountWithServerConfigId() + }.map { + it.map { (userId, serverConfig) -> + userId.toModel() to serverConfigMapper.fromEntity(serverConfig) + }.toMap() + } + internal fun ManagedByDTO.toDao() = when (this) { ManagedByDTO.WIRE -> ManagedByEntity.WIRE ManagedByDTO.SCIM -> ManagedByEntity.SCIM diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/di/MapperProvider.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/di/MapperProvider.kt index 6bb0ccd60f0..1d414588ac6 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/di/MapperProvider.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/di/MapperProvider.kt @@ -99,8 +99,8 @@ import com.wire.kalium.logic.data.user.type.UserEntityTypeMapperImpl internal object MapperProvider { fun apiVersionMapper(): ApiVersionMapper = ApiVersionMapperImpl() fun idMapper(): IdMapper = IdMapperImpl() - fun serverConfigMapper(): ServerConfigMapper = ServerConfigMapperImpl(apiVersionMapper(), idMapper()) - fun sessionMapper(): SessionMapper = SessionMapperImpl(idMapper()) + fun serverConfigMapper(): ServerConfigMapper = ServerConfigMapperImpl(apiVersionMapper()) + fun sessionMapper(): SessionMapper = SessionMapperImpl() fun availabilityStatusMapper(): AvailabilityStatusMapper = AvailabilityStatusMapperImpl() fun connectionStateMapper(): ConnectionStateMapper = ConnectionStateMapperImpl() fun userMapper(): UserMapper = UserMapperImpl() diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/SessionManagerExt.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/SessionManagerExt.kt index dbfe45ff4da..360c0600cf6 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/SessionManagerExt.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/SessionManagerExt.kt @@ -21,10 +21,14 @@ package com.wire.kalium.logic.feature import com.wire.kalium.logic.data.auth.login.ProxyCredentials import com.wire.kalium.logic.di.MapperProvider +import com.wire.kalium.logic.kaliumLogger import com.wire.kalium.network.session.SessionManager -internal fun SessionManager.getProxyCredentials(): ProxyCredentials? = - MapperProvider.sessionMapper().fromDTOToProxyCredentialsModel(proxyCredentials()) +internal fun SessionManager.getProxyCredentials(): ProxyCredentials? { + val cred = proxyCredentials() + kaliumLogger.d("getProxyCredentials: $cred") + return MapperProvider.sessionMapper().fromDTOToProxyCredentialsModel(cred) +} internal fun SessionManager.getServerConfig() = MapperProvider.serverConfigMapper().fromDTO(serverConfig()) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt index e865da3088f..28aec5b7831 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt @@ -390,6 +390,7 @@ import com.wire.kalium.network.networkContainer.AuthenticatedNetworkContainer import com.wire.kalium.network.session.SessionManager import com.wire.kalium.persistence.client.ClientRegistrationStorage import com.wire.kalium.persistence.client.ClientRegistrationStorageImpl +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider import com.wire.kalium.util.DelicateKaliumApi import kotlinx.coroutines.CoroutineScope @@ -408,6 +409,7 @@ class UserSessionScope internal constructor( private val userId: UserId, private val globalScope: GlobalKaliumScope, private val globalCallManager: GlobalCallManager, + private val globalDatabaseProvider: GlobalDatabaseProvider, private val globalPreferences: GlobalPrefProvider, authenticationScopeProvider: AuthenticationScopeProvider, private val userSessionWorkScheduler: UserSessionWorkScheduler, @@ -533,14 +535,16 @@ class UserSessionScope internal constructor( kaliumConfigs, sessionManager.serverConfig().metaData.commonApiVersion.version ) - val authenticationScope: AuthenticationScope = authenticationScopeProvider.provide( - sessionManager.getServerConfig(), - sessionManager.getProxyCredentials(), - globalScope.serverConfigRepository, - networkStateObserver, - kaliumConfigs::certPinningConfig, - mockEngine = kaliumConfigs.kaliumMockEngine?.mockEngine - ) + + val authenticationScope: AuthenticationScope by lazy { + authenticationScopeProvider.provide( + sessionManager.getServerConfig(), + sessionManager.getProxyCredentials(), + networkStateObserver, + globalDatabase = globalDatabaseProvider, + kaliumConfigs = kaliumConfigs, + ) + } internal val userConfigRepository: UserConfigRepository get() = UserConfigDataSource( @@ -1482,7 +1486,7 @@ class UserSessionScope internal constructor( renamedConversationHandler, qualifiedIdMapper, team.isSelfATeamMember, - globalScope.serverConfigRepository, + authenticationScope.serverConfigRepository, userStorage, userPropertyRepository, oneOnOneResolver, @@ -1551,7 +1555,7 @@ class UserSessionScope internal constructor( connectionRepository, qualifiedIdMapper, globalScope.sessionRepository, - globalScope.serverConfigRepository, + authenticationScope.serverConfigRepository, userId, userStorage.database.metadataDAO, userPropertyRepository, diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/appVersioning/ObserveIfAppUpdateRequiredUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/appVersioning/ObserveIfAppUpdateRequiredUseCase.kt index 953056eb2cd..26834de1b8e 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/appVersioning/ObserveIfAppUpdateRequiredUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/appVersioning/ObserveIfAppUpdateRequiredUseCase.kt @@ -15,11 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ -@file:Suppress("konsist.useCasesShouldNotAccessNetworkLayerDirectly") +@file:Suppress("konsist.useCasesShouldNotAccessNetworkLayerDirectly", "konsist.useCasesShouldNotAccessDaoLayerDirectly") package com.wire.kalium.logic.feature.appVersioning -import com.wire.kalium.logic.configuration.server.ServerConfigRepository +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.data.auth.login.ProxyCredentials import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.feature.UserSessionScopeProvider @@ -31,6 +31,7 @@ import com.wire.kalium.logic.functional.intervalFlow import com.wire.kalium.logic.functional.onFailure import com.wire.kalium.logic.kaliumLogger import com.wire.kalium.network.NetworkStateObserver +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.util.DateTimeUtil import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async @@ -55,10 +56,11 @@ interface ObserveIfAppUpdateRequiredUseCase { } class ObserveIfAppUpdateRequiredUseCaseImpl internal constructor( - private val serverConfigRepository: ServerConfigRepository, + private val customServerConfigRepository: CustomServerConfigRepository, private val authenticationScopeProvider: AuthenticationScopeProvider, private val userSessionScopeProvider: UserSessionScopeProvider, private val networkStateObserver: NetworkStateObserver, + private val globalDatabaseProvider: GlobalDatabaseProvider, private val kaliumConfigs: KaliumConfigs ) : ObserveIfAppUpdateRequiredUseCase { @@ -70,7 +72,7 @@ class ObserveIfAppUpdateRequiredUseCaseImpl internal constructor( return intervalFlow(CHECK_APP_VERSION_FREQUENCY_MS) .flatMapLatest { - serverConfigRepository.getServerConfigsWithUserIdAfterTheDate(dateForChecking) + customServerConfigRepository.getServerConfigsWithUserIdAfterTheDate(dateForChecking) .onFailure { kaliumLogger.e("$TAG: error while getting configs for checking $it") } .getOrElse(flowOf(listOf())) } @@ -103,12 +105,11 @@ class ObserveIfAppUpdateRequiredUseCaseImpl internal constructor( async { val isUpdateRequired = authenticationScopeProvider .provide( - serverConfig, - proxyCredentials, - serverConfigRepository, - networkStateObserver, - kaliumConfigs::certPinningConfig, - kaliumConfigs.kaliumMockEngine?.mockEngine + serverConfig = serverConfig, + proxyCredentials = proxyCredentials, + networkStateObserver = networkStateObserver, + globalDatabase = globalDatabaseProvider, + kaliumConfigs = kaliumConfigs, ) .checkIfUpdateRequired(currentAppVersion, serverConfig.links.blackList) serverConfig.id to isUpdateRequired @@ -123,7 +124,7 @@ class ObserveIfAppUpdateRequiredUseCaseImpl internal constructor( .toSet() if (noUpdateRequiredConfigIds.isNotEmpty()) { - serverConfigRepository.updateAppBlackListCheckDate(noUpdateRequiredConfigIds, currentDate) + customServerConfigRepository.updateAppBlackListCheckDate(noUpdateRequiredConfigIds, currentDate) } configIdWithFreshFlag.any { (_, isUpdateRequired) -> isUpdateRequired } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCase.kt index 3d237de3ca9..81d20366f7c 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCase.kt @@ -15,18 +15,24 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ +@file:Suppress("konsist.useCasesShouldNotAccessDaoLayerDirectly",) package com.wire.kalium.logic.feature.auth import com.wire.kalium.logic.CoreFailure -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.data.auth.AccountTokens +import com.wire.kalium.logic.configuration.server.ServerConfigMapper import com.wire.kalium.logic.data.auth.login.ProxyCredentials import com.wire.kalium.logic.data.session.SessionRepository import com.wire.kalium.logic.data.user.SsoId import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.functional.fold +import com.wire.kalium.logic.functional.getOrElse +import com.wire.kalium.logic.functional.map import com.wire.kalium.logic.functional.onSuccess +import com.wire.kalium.logic.wrapStorageRequest +import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO /** * Adds an authenticated user to the session @@ -34,7 +40,8 @@ import com.wire.kalium.logic.functional.onSuccess */ class AddAuthenticatedUserUseCase internal constructor( private val sessionRepository: SessionRepository, - private val serverConfigRepository: ServerConfigRepository + private val serverConfigurationDAO: ServerConfigurationDAO, + private val serverConfigMapper: ServerConfigMapper = MapperProvider.serverConfigMapper() ) { sealed class Result { data class Success(val userId: UserId) : Result() @@ -89,7 +96,12 @@ class AddAuthenticatedUserUseCase internal constructor( { Result.Failure.Generic(it) }, { oldSession -> val newServerConfig = - serverConfigRepository.configById(newServerConfigId).fold({ return Result.Failure.Generic(it) }, { it }) + wrapStorageRequest { + serverConfigurationDAO.configById(newServerConfigId) + }.map { + serverConfigMapper.fromEntity(it) + }.getOrElse { return Result.Failure.Generic(it) } + if (oldSession.serverConfig.links == newServerConfig.links) { storeUser( serverConfigId = newServerConfigId, diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AuthenticationScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AuthenticationScope.kt index 4eef8aecad4..28913570cbd 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AuthenticationScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/AuthenticationScope.kt @@ -15,14 +15,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ -@file:Suppress("konsist.useCasesShouldNotAccessNetworkLayerDirectly") +@file:Suppress("konsist.useCasesShouldNotAccessDaoLayerDirectly", "konsist.useCasesShouldNotAccessNetworkLayerDirectly") package com.wire.kalium.logic.feature.auth import co.touchlab.stately.collections.ConcurrentMutableMap import com.wire.kalium.logic.configuration.appVersioning.AppVersionRepository import com.wire.kalium.logic.configuration.appVersioning.AppVersionRepositoryImpl +import com.wire.kalium.logic.configuration.server.CustomServerConfigDataSource +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfig +import com.wire.kalium.logic.configuration.server.ServerConfigDataSource import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.data.auth.login.LoginRepository import com.wire.kalium.logic.data.auth.login.LoginRepositoryImpl @@ -39,10 +42,10 @@ import com.wire.kalium.logic.feature.appVersioning.CheckIfUpdateRequiredUseCaseI import com.wire.kalium.logic.feature.auth.sso.SSOLoginScope import com.wire.kalium.logic.feature.auth.verification.RequestSecondFactorVerificationCodeUseCase import com.wire.kalium.logic.feature.register.RegisterScope +import com.wire.kalium.logic.featureFlags.KaliumConfigs import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.network.networkContainer.UnauthenticatedNetworkContainer -import com.wire.kalium.network.session.CertificatePinning -import io.ktor.client.engine.HttpClientEngine +import com.wire.kalium.persistence.db.GlobalDatabaseProvider class AuthenticationScopeProvider internal constructor( private val userAgent: String @@ -57,44 +60,49 @@ class AuthenticationScopeProvider internal constructor( internal fun provide( serverConfig: ServerConfig, proxyCredentials: ProxyCredentials?, - serverConfigRepository: ServerConfigRepository, networkStateObserver: NetworkStateObserver, - certConfig: () -> CertificatePinning, - mockEngine: HttpClientEngine? + globalDatabase: GlobalDatabaseProvider, + kaliumConfigs: KaliumConfigs ): AuthenticationScope = authenticationScopeStorage.computeIfAbsent(serverConfig to proxyCredentials) { AuthenticationScope( userAgent, serverConfig, proxyCredentials, - serverConfigRepository, networkStateObserver, - certConfig, - mockEngine + kaliumConfigs = kaliumConfigs, + globalDatabase = globalDatabase ) } } -@Suppress("LongParameterList") class AuthenticationScope internal constructor( private val userAgent: String, private val serverConfig: ServerConfig, private val proxyCredentials: ProxyCredentials?, - private val serverConfigRepository: ServerConfigRepository, private val networkStateObserver: NetworkStateObserver, - certConfig: () -> CertificatePinning, - mockEngine: HttpClientEngine? + private val globalDatabase: GlobalDatabaseProvider, + private val kaliumConfigs: KaliumConfigs, ) { + private val unauthenticatedNetworkContainer: UnauthenticatedNetworkContainer by lazy { UnauthenticatedNetworkContainer.create( networkStateObserver, - MapperProvider.serverConfigMapper().toDTO(serverConfig), - proxyCredentials?.let { MapperProvider.sessionMapper().fromModelToProxyCredentialsDTO(it) }, - userAgent, - certificatePinning = certConfig(), - mockEngine + serverConfigDTO = MapperProvider.serverConfigMapper().toDTO(serverConfig), + proxyCredentials = proxyCredentials?.let { MapperProvider.sessionMapper().fromModelToProxyCredentialsDTO(it) }, + userAgent = userAgent, + developmentApiEnabled = kaliumConfigs.developmentApiEnabled, + certificatePinning = kaliumConfigs.certPinningConfig, + mockEngine = kaliumConfigs.kaliumMockEngine?.mockEngine ) } + + internal val serverConfigRepository: ServerConfigRepository + get() = ServerConfigDataSource( + globalDatabase.serverConfigurationDAO, + unauthenticatedNetworkContainer.remoteVersion, + ) + private val loginRepository: LoginRepository get() = LoginRepositoryImpl(unauthenticatedNetworkContainer.loginApi) @@ -102,6 +110,14 @@ class AuthenticationScope internal constructor( get() = RegisterAccountDataSource( unauthenticatedNetworkContainer.registerApi ) + + private val customServerConfigRepository: CustomServerConfigRepository + get() = CustomServerConfigDataSource( + unauthenticatedNetworkContainer.serverConfigApi, + kaliumConfigs.developmentApiEnabled, + globalDatabase.serverConfigurationDAO + ) + internal val ssoLoginRepository: SSOLoginRepository get() = SSOLoginRepositoryImpl(unauthenticatedNetworkContainer.sso, unauthenticatedNetworkContainer.domainLookupApi) @@ -134,7 +150,11 @@ class AuthenticationScope internal constructor( val domainLookup: DomainLookupUseCase get() = DomainLookupUseCase( - serverConfigRepository = serverConfigRepository, + serverConfigApi = customServerConfigRepository, ssoLoginRepository = ssoLoginRepository ) + + val currentServerConfig: () -> ServerConfig = { + serverConfig + } } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCase.kt index d36d89abd0f..710f0ba7e4f 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCase.kt @@ -18,8 +18,8 @@ package com.wire.kalium.logic.feature.auth import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.data.auth.login.SSOLoginRepository import com.wire.kalium.logic.functional.flatMap import com.wire.kalium.logic.functional.fold @@ -31,7 +31,7 @@ import com.wire.kalium.logic.functional.fold * @param email the email to lookup */ class DomainLookupUseCase internal constructor( - private val serverConfigRepository: ServerConfigRepository, + private val serverConfigApi: CustomServerConfigRepository, private val ssoLoginRepository: SSOLoginRepository ) { suspend operator fun invoke(email: String): Result { @@ -41,7 +41,7 @@ class DomainLookupUseCase internal constructor( } return ssoLoginRepository.domainLookup(domain).flatMap { - serverConfigRepository.fetchRemoteConfig(it.configJsonUrl) + serverConfigApi.fetchRemoteConfig(it.configJsonUrl) }.fold(Result::Failure, Result::Success) } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/autoVersioningAuth/AutoVersionAuthScopeUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/autoVersioningAuth/AutoVersionAuthScopeUseCase.kt index ad5fad6e22d..49187d69bcd 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/autoVersioningAuth/AutoVersionAuthScopeUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/auth/autoVersioningAuth/AutoVersionAuthScopeUseCase.kt @@ -15,11 +15,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ +@file:Suppress("konsist.useCasesShouldNotAccessNetworkLayerDirectly") package com.wire.kalium.logic.feature.auth.autoVersioningAuth import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.CoreLogicCommon +import com.wire.kalium.logic.configuration.server.CommonApiVersionType import com.wire.kalium.logic.configuration.server.ServerConfig import com.wire.kalium.logic.data.auth.login.ProxyCredentials import com.wire.kalium.logic.failure.ServerConfigFailure @@ -27,6 +29,7 @@ import com.wire.kalium.logic.feature.auth.AuthenticationScope import com.wire.kalium.logic.featureFlags.KaliumConfigs import com.wire.kalium.logic.functional.fold import com.wire.kalium.logic.kaliumLogger +import com.wire.kalium.network.SupportedApiVersions /** * This use case is responsible for obtaining the authentication scope for the current version of the app. @@ -39,9 +42,22 @@ class AutoVersionAuthScopeUseCase( ) { suspend operator fun invoke( - proxyAuthentication: ProxyAuthentication = ProxyAuthentication.None + proxyCredentials: ProxyCredentials? ): Result = - coreLogic.getGlobalScope().serverConfigRepository.getOrFetchMetadata(serverLinks).fold({ + coreLogic.getAuthenticationScope( + serverConfig = ServerConfig( + links = serverLinks, + id = "initialization", + metaData = ServerConfig.MetaData( + federation = false, + commonApiVersion = CommonApiVersionType.Valid( + SupportedApiVersions.first() + ), + domain = null + ) + ), + proxyCredentials = proxyCredentials + ).serverConfigRepository.getOrFetchMetadata(serverLinks).fold({ handleError(it) }, { serverConfig -> // Backend team doesn't want any clients using the development APIs in production, so @@ -50,10 +66,6 @@ class AutoVersionAuthScopeUseCase( if (kaliumConfigs.developmentApiEnabled && serverConfig.links == ServerConfig.PRODUCTION) { return Result.Failure.Generic(CoreFailure.DevelopmentAPINotAllowedOnProduction) } - val proxyCredentials = when (proxyAuthentication) { - is ProxyAuthentication.None -> null - is ProxyAuthentication.UsernameAndPassword -> proxyAuthentication.proxyCredentials - } Result.Success(coreLogic.getAuthenticationScope(serverConfig, proxyCredentials)) }) @@ -73,10 +85,4 @@ class AutoVersionAuthScopeUseCase( data class Generic(val genericFailure: CoreFailure) : Failure() } } - - sealed interface ProxyAuthentication { - data object None : ProxyAuthentication - - data class UsernameAndPassword(val proxyCredentials: ProxyCredentials) : ProxyAuthentication - } } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCase.kt index 844d6d1dcc6..d24a3d38eba 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCase.kt @@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.map * If there is an enforced app lock on any of the user's accounts, the app lock is not editable. */ interface ObserveIsAppLockEditableUseCase { - operator fun invoke(): Flow + suspend operator fun invoke(): Flow } class ObserveIsAppLockEditableUseCaseImpl internal constructor( @@ -41,7 +41,7 @@ class ObserveIsAppLockEditableUseCaseImpl internal constructor( private val sessionRepository: SessionRepository ) : ObserveIsAppLockEditableUseCase { @OptIn(ExperimentalCoroutinesApi::class) - override operator fun invoke(): Flow = + override suspend operator fun invoke(): Flow = sessionRepository.allValidSessionsFlow() .flatMapRight { accounts -> combine( diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/FetchApiVersionUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/FetchApiVersionUseCase.kt deleted file mode 100644 index 776d61c1094..00000000000 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/FetchApiVersionUseCase.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.feature.server - -import com.wire.kalium.logic.CoreFailure -import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository -import com.wire.kalium.logic.failure.ServerConfigFailure -import com.wire.kalium.logic.functional.fold - -/** - * Fetches the server api version, for the given server backend. - */ -interface FetchApiVersionUseCase { - /** - * @param serverLinks the server backend links to fetch the api version from - * @return the [FetchApiVersionResult] the server configuration version if successful, otherwise a mapped failure. - */ - suspend operator fun invoke(serverLinks: ServerConfig.Links): FetchApiVersionResult -} - -class FetchApiVersionUseCaseImpl internal constructor( - private val configRepository: ServerConfigRepository -) : FetchApiVersionUseCase { - override suspend operator fun invoke(serverLinks: ServerConfig.Links): FetchApiVersionResult = - configRepository.fetchApiVersionAndStore(serverLinks) - .fold( - { handleError(it) }, - { FetchApiVersionResult.Success(it) } - ) - - private fun handleError(coreFailure: CoreFailure): FetchApiVersionResult.Failure = - when (coreFailure) { - is ServerConfigFailure.NewServerVersion -> FetchApiVersionResult.Failure.TooNewVersion - is ServerConfigFailure.UnknownServerVersion -> FetchApiVersionResult.Failure.UnknownServerVersion - else -> FetchApiVersionResult.Failure.UnknownServerVersion - } -} - -sealed class FetchApiVersionResult { - class Success(val serverConfig: ServerConfig) : FetchApiVersionResult() - - sealed class Failure : FetchApiVersionResult() { - data object UnknownServerVersion : Failure() - data object TooNewVersion : Failure() - data class Generic(val genericFailure: CoreFailure) : Failure() - } -} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/GetServerConfigUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/GetServerConfigUseCase.kt index ec8fccd1db4..1582615e8c1 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/GetServerConfigUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/GetServerConfigUseCase.kt @@ -19,21 +19,21 @@ package com.wire.kalium.logic.feature.server import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.functional.fold /** * Gets the [ServerConfig.Links] stored locally, using the url as a key. */ class GetServerConfigUseCase internal constructor( - private val configRepository: ServerConfigRepository + private val customServerConfigRepository: CustomServerConfigRepository ) { /** * @param url the url to use as a key to get the [ServerConfig.Links] * @return the [Result] with the [ServerConfig.Links] if successful, otherwise a mapped failure. */ - suspend operator fun invoke(url: String): GetServerConfigResult = configRepository.fetchRemoteConfig(url).fold({ + suspend operator fun invoke(url: String): GetServerConfigResult = customServerConfigRepository.fetchRemoteConfig(url).fold({ GetServerConfigResult.Failure.Generic(it) }, { GetServerConfigResult.Success(it) }) } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/ObserveServerConfigUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/ObserveServerConfigUseCase.kt deleted file mode 100644 index 8a6c6ce45ff..00000000000 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/ObserveServerConfigUseCase.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.feature.server - -import com.wire.kalium.logic.CoreFailure -import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository -import com.wire.kalium.logic.functional.fold -import com.wire.kalium.logic.functional.map -import com.wire.kalium.logic.functional.onFailure -import com.wire.kalium.logic.functional.onSuccess -import kotlinx.coroutines.flow.Flow - -/** - * Observes for changes and returns the list of [ServerConfig] stored locally. - */ -class ObserveServerConfigUseCase internal constructor( - private val serverConfigRepository: ServerConfigRepository -) { - sealed class Result { - data class Success(val value: Flow>) : Result() - sealed class Failure : Result() { - data class Generic(val genericFailure: CoreFailure) : Failure() - } - } - - /** - * @return the [Result] with the [Flow] list of [ServerConfig] if successful, otherwise a mapped failure. - */ - suspend operator fun invoke(): Result { - serverConfigRepository.configList().map { configList -> - configList.isNullOrEmpty() - }.onSuccess { isEmpty -> - if (isEmpty) { - // TODO: store all of the configs from the build json file - ServerConfig.DEFAULT.also { config -> - // TODO: what do do if one of the insert failed - serverConfigRepository.fetchApiVersionAndStore(config).onFailure { - return handleError(it) - } - } - } - } - - return serverConfigRepository.configFlow().fold({ - Result.Failure.Generic(it) - }, { - Result.Success(it) - }) - } - - private fun handleError(coreFailure: CoreFailure): Result.Failure { - return Result.Failure.Generic(coreFailure) - } -} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/ServerConfigForAccountUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/ServerConfigForAccountUseCase.kt index 3496c7d9b6f..921a05b71a6 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/ServerConfigForAccountUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/ServerConfigForAccountUseCase.kt @@ -15,27 +15,35 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ +@file:Suppress("konsist.useCasesShouldNotAccessDaoLayerDirectly") package com.wire.kalium.logic.feature.server import com.wire.kalium.logic.StorageFailure import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository +import com.wire.kalium.logic.configuration.server.ServerConfigMapper +import com.wire.kalium.logic.data.id.toDao import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.functional.fold +import com.wire.kalium.logic.functional.map +import com.wire.kalium.logic.wrapStorageRequest +import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO /** * Gets the server configuration for the given user. */ class ServerConfigForAccountUseCase internal constructor( - private val serverConfigRepository: ServerConfigRepository + private val dao: ServerConfigurationDAO, + private val serverConfigMapper: ServerConfigMapper = MapperProvider.serverConfigMapper() ) { /** * @param userId the id of the user * @return the [ServerConfig] for the given user if successful, otherwise a [StorageFailure] */ - suspend operator fun invoke(userId: UserId) = - serverConfigRepository.configForUser(userId) + suspend operator fun invoke(userId: UserId): Result = + wrapStorageRequest { dao.configForUser(userId.toDao()) } + .map { serverConfigMapper.fromEntity(it) } .fold(Result::Failure, Result::Success) sealed class Result { diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCase.kt index 235f257c18b..73785288103 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCase.kt @@ -19,8 +19,8 @@ package com.wire.kalium.logic.feature.server import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.functional.fold import io.ktor.http.URLBuilder @@ -37,7 +37,7 @@ fun interface StoreServerConfigUseCase { } internal class StoreServerConfigUseCaseImpl( - private val configRepository: ServerConfigRepository + private val configRepository: CustomServerConfigRepository ) : StoreServerConfigUseCase { override suspend fun invoke(links: ServerConfig.Links, versionInfo: ServerConfig.VersionInfo): StoreServerConfigResult { diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionsUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionsUseCase.kt index 315a5790ad8..258eab2ac2d 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionsUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionsUseCase.kt @@ -15,11 +15,27 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ +@file:Suppress("konsist.useCasesShouldNotAccessDaoLayerDirectly") package com.wire.kalium.logic.feature.server +import com.wire.kalium.logic.configuration.server.ServerConfig import com.wire.kalium.logic.configuration.server.ServerConfigRepository -import com.wire.kalium.logic.functional.onSuccess +import com.wire.kalium.logic.data.auth.login.ProxyCredentials +import com.wire.kalium.logic.data.id.toDao +import com.wire.kalium.logic.data.session.SessionMapper +import com.wire.kalium.logic.data.session.SessionRepository +import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.di.MapperProvider +import com.wire.kalium.logic.functional.getOrElse +import com.wire.kalium.logic.functional.map +import com.wire.kalium.logic.kaliumLogger +import com.wire.kalium.logic.wrapStorageNullableRequest +import com.wire.kalium.persistence.client.AuthTokenStorage +import io.ktor.util.collections.ConcurrentSet +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.joinAll +import kotlinx.coroutines.launch /** * Iterates over all locally stored server configs and update each api version @@ -29,13 +45,41 @@ interface UpdateApiVersionsUseCase { } class UpdateApiVersionsUseCaseImpl internal constructor( - private val configRepository: ServerConfigRepository + private val sessionRepository: SessionRepository, + private val tokenStorage: AuthTokenStorage, + private val serverConfigRepoProvider: (serverConfig: ServerConfig, proxyCredentials: ProxyCredentials?) -> ServerConfigRepository, + private val sessionMapper: SessionMapper = MapperProvider.sessionMapper() ) : UpdateApiVersionsUseCase { override suspend operator fun invoke() { - configRepository.configList().onSuccess { configList -> - configList.forEach { - configRepository.updateConfigApiVersion(it.id) + coroutineScope { + val updatedServerId = ConcurrentSet() + sessionRepository.validSessionsWithServerConfig().getOrElse { + return@coroutineScope + }.map { (userId, serverConfig) -> + launch { + if (updatedServerId.contains(serverConfig.id)) { + return@launch + } + updatedServerId.add(serverConfig.id) + updateApiForUser(userId, serverConfig) + } + }.joinAll() + } + } + + private suspend fun updateApiForUser(userId: UserId, serverConfig: ServerConfig) { + val proxyCredentials: ProxyCredentials? = if (serverConfig.links.apiProxy?.needsAuthentication == true) { + wrapStorageNullableRequest { + tokenStorage.proxyCredentials(userId.toDao()) + }.map { + it?.let { sessionMapper.formEntityToProxyModel(it) } + }.getOrElse { + kaliumLogger.d("No proxy credentials found for user ${userId.toLogString()}}") + return } + } else { + null } + serverConfigRepoProvider(serverConfig, proxyCredentials).updateConfigApiVersion(serverConfig) } } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/ObserveValidAccountsUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/ObserveValidAccountsUseCase.kt index 55d9f0611ec..c2ebe8cbb34 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/ObserveValidAccountsUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/ObserveValidAccountsUseCase.kt @@ -41,7 +41,7 @@ interface ObserveValidAccountsUseCase { /** * @return a [Flow] of the list of valid accounts and their associated team. */ - operator fun invoke(): Flow>> + suspend operator fun invoke(): Flow>> } internal class ObserveValidAccountsUseCaseImpl internal constructor( @@ -51,7 +51,7 @@ internal class ObserveValidAccountsUseCaseImpl internal constructor( ) : ObserveValidAccountsUseCase { @OptIn(ExperimentalCoroutinesApi::class) - override fun invoke(): Flow>> = + override suspend fun invoke(): Flow>> = sessionRepository.allValidSessionsFlow() .flatMapRight { accountList -> if (accountList.isEmpty()) { diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/functional/Either.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/functional/Either.kt index b4270ca94d0..24370ec60b4 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/functional/Either.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/functional/Either.kt @@ -159,7 +159,7 @@ inline fun Either.mapLeft(fn: (L) -> (T)): Either = * Returns the value from this `Right` or the given argument if this is a `Left`. * Right(12).getOrElse(17) RETURNS 12 and Left(12).getOrElse(17) RETURNS 17 */ -fun Either.getOrElse(value: R): R = +inline fun Either.getOrElse(value: R): R = when (this) { is Left -> value is Right -> this.value @@ -169,7 +169,7 @@ fun Either.getOrElse(value: R): R = * Returns the value from this `Right` or the result of `fn` if this is a `Left`. * Right(12).getOrElse{ it + 3 } RETURNS 12 and Left(12).getOrElse{ it + 3 } RETURNS 15 */ -fun Either.getOrElse(fn: (L) -> (R)): R = +inline fun Either.getOrElse(fn: (L) -> (R)): R = when (this) { is Left -> fn(value) is Right -> this.value @@ -179,7 +179,7 @@ fun Either.getOrElse(fn: (L) -> (R)): R = * Returns the value from this `Right` or null if this is a `Left`. * Right(12).getOrNull() RETURNS 12 and Left(12).getOrNull() RETURNS null */ -fun Either.getOrNull(): R? = +inline fun Either.getOrNull(): R? = when (this) { is Left -> null is Right -> this.value diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/CustomServerConfigRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/CustomServerConfigRepositoryTest.kt new file mode 100644 index 00000000000..3bffc343166 --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/CustomServerConfigRepositoryTest.kt @@ -0,0 +1,281 @@ +/* + * 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.configuration + +import com.wire.kalium.logic.configuration.server.CommonApiVersionType +import com.wire.kalium.logic.configuration.server.CustomServerConfigDataSource +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository +import com.wire.kalium.logic.configuration.server.ServerConfig +import com.wire.kalium.logic.util.shouldSucceed +import com.wire.kalium.logic.util.stubs.newServerConfig +import com.wire.kalium.logic.util.stubs.newServerConfigDTO +import com.wire.kalium.logic.util.stubs.newServerConfigEntity +import com.wire.kalium.network.BackendMetaDataUtil +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.tools.ServerConfigDTO +import com.wire.kalium.network.utils.NetworkResponse +import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO +import com.wire.kalium.persistence.model.ServerConfigEntity +import io.mockative.Mock +import io.mockative.any +import io.mockative.classOf +import io.mockative.given +import io.mockative.mock +import io.mockative.once +import io.mockative.verify +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runTest +import kotlin.properties.Delegates +import kotlin.test.Test +import kotlin.test.assertEquals +class CustomServerConfigRepositoryTest { + + @Test + fun givenUrl_whenFetchingServerConfigSuccess_thenTheSuccessIsReturned() = runTest { + val (arrangement, repository) = Arrangement().withSuccessConfigResponse().arrange() + val expected = arrangement.SERVER_CONFIG.links + val serverConfigUrl = arrangement.SERVER_CONFIG_URL + + val actual = repository.fetchRemoteConfig(serverConfigUrl) + + actual.shouldSucceed { assertEquals(expected, it) } + verify(arrangement.serverConfigApi) + .coroutine { arrangement.serverConfigApi.fetchServerConfig(serverConfigUrl) } + .wasInvoked(exactly = once) + } + + @Test + fun givenStoredConfig_whenAddingTheSameOneWithNewApiVersionParams_thenStoredOneShouldBeUpdatedAndReturned() = runTest { + val (arrangement, repository) = Arrangement() + .withUpdatedServerConfig() + .arrange() + + repository + .storeConfig(arrangement.expectedServerConfig.links, arrangement.expectedServerConfig.metaData) + .shouldSucceed { assertEquals(arrangement.expectedServerConfig, it) } + + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::configByLinks) + .with(any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::insert) + .with(any()) + .wasNotInvoked() + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::updateApiVersion) + .with(any(), any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::setFederationToTrue) + .with(any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .function(arrangement.serverConfigurationDAO::configById) + .with(any()) + .wasInvoked(exactly = once) + } + + @Test + fun givenStoredConfig_whenAddingNewOne_thenNewOneShouldBeInsertedAndReturned() = runTest { + val expected = newServerConfig(1) + val (arrangement, repository) = Arrangement() + .withConfigForNewRequest(newServerConfigEntity(1)) + .arrange() + + repository + .storeConfig(expected.links, expected.metaData) + .shouldSucceed { assertEquals(it, expected) } + + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::configByLinks) + .with(any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::insert) + .with(any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::updateApiVersion) + .with(any(), any()) + .wasNotInvoked() + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::setFederationToTrue) + .with(any()) + .wasNotInvoked() + verify(arrangement.serverConfigurationDAO) + .function(arrangement.serverConfigurationDAO::configById) + .with(any()) + .wasInvoked(exactly = once) + } + + @Test + fun givenStoredConfigLinksAndVersionInfoData_whenAddingNewOne_thenCommonApiShouldBeCalculatedAndConfigShouldBeStored() = runTest { + val expectedServerConfig = newServerConfig(1) + val expectedServerConfigDTO = newServerConfigDTO(1) + val expectedVersionInfo = ServerConfig.VersionInfo( + expectedServerConfig.metaData.federation, + listOf(expectedServerConfig.metaData.commonApiVersion.version), + expectedServerConfig.metaData.domain, + null + ) + val (arrangement, repository) = Arrangement() + .withConfigForNewRequest(newServerConfigEntity(1)) + .withCalculateApiVersion(expectedServerConfigDTO.metaData) + .arrange() + + repository + .storeConfig(expectedServerConfig.links, expectedVersionInfo) + .shouldSucceed { assertEquals(it, expectedServerConfig) } + + verify(arrangement.backendMetaDataUtil) + .function(arrangement.backendMetaDataUtil::calculateApiVersion) + .with(any(), any(), any(), any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::configByLinks) + .with(any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::insert) + .with(any()) + .wasInvoked(exactly = once) + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::updateApiVersion) + .with(any(), any()) + .wasNotInvoked() + verify(arrangement.serverConfigurationDAO) + .suspendFunction(arrangement.serverConfigurationDAO::setFederationToTrue) + .with(any()) + .wasNotInvoked() + verify(arrangement.serverConfigurationDAO) + .function(arrangement.serverConfigurationDAO::configById) + .with(any()) + .wasInvoked(exactly = once) + } + + private class Arrangement { + val SERVER_CONFIG_URL = "https://test.test/test.json" + val SERVER_CONFIG_RESPONSE = newServerConfigDTO(1) + val SERVER_CONFIG = newServerConfig(1) + + @Mock + val serverConfigApi = mock(classOf()) + + var developmentApiEnabled by Delegates.notNull() + + @Mock + val serverConfigurationDAO = mock(classOf()) + init { + developmentApiEnabled = false + } + + @Mock + val backendMetaDataUtil = mock(classOf()) + + private var customServerConfigRepository: CustomServerConfigRepository = + CustomServerConfigDataSource(serverConfigApi, developmentApiEnabled, serverConfigurationDAO, backendMetaDataUtil) + + val serverConfigEntity = newServerConfigEntity(1) + val expectedServerConfig = newServerConfig(1).copy( + metaData = ServerConfig.MetaData( + commonApiVersion = CommonApiVersionType.Valid(5), + federation = true, + domain = serverConfigEntity.metaData.domain + ) + ) + + + + suspend fun withConfigForNewRequest(serverConfigEntity: ServerConfigEntity): Arrangement { + given(serverConfigurationDAO) + .coroutine { configByLinks(serverConfigEntity.links) } + .then { null } + given(serverConfigurationDAO) + .function(serverConfigurationDAO::configById) + .whenInvokedWith(any()) + .then { newServerConfigEntity(1) } + return this + } + + suspend fun withSuccessConfigResponse(): Arrangement { + given(serverConfigApi) + .coroutine { serverConfigApi.fetchServerConfig(SERVER_CONFIG_URL) } + .then { NetworkResponse.Success(SERVER_CONFIG_RESPONSE.links, mapOf(), 200) } + return this + } + + suspend fun withDaoEntityResponse(): Arrangement { + given(serverConfigurationDAO).coroutine { allConfig() } + .then { listOf(newServerConfigEntity(1), newServerConfigEntity(2), newServerConfigEntity(3)) } + return this + } + + fun withConfigById(serverConfig: ServerConfigEntity): Arrangement { + given(serverConfigurationDAO) + .function(serverConfigurationDAO::configById) + .whenInvokedWith(any()) + .then { serverConfig } + return this + } + + fun withConfigByLinks(serverConfigEntity: ServerConfigEntity?): Arrangement { + given(serverConfigurationDAO) + .suspendFunction(serverConfigurationDAO::configByLinks) + .whenInvokedWith(any()) + .thenReturn(serverConfigEntity) + return this + } + + suspend fun withDaoEntityFlowResponse(): Arrangement { + given(serverConfigurationDAO).coroutine { allConfigFlow() } + .then { flowOf(listOf(newServerConfigEntity(1), newServerConfigEntity(2), newServerConfigEntity(3))) } + return this + } + + suspend fun withUpdatedServerConfig(): Arrangement { + val newServerConfigEntity = serverConfigEntity.copy( + metaData = serverConfigEntity.metaData.copy( + apiVersion = 5, + federation = true + ) + ) + + given(serverConfigurationDAO) + .coroutine { configByLinks(serverConfigEntity.links) } + .then { serverConfigEntity } + given(serverConfigurationDAO) + .function(serverConfigurationDAO::configById) + .whenInvokedWith(any()) + .then { newServerConfigEntity } + + return this + } + + fun withCalculateApiVersion(result: ServerConfigDTO.MetaData): Arrangement { + given(backendMetaDataUtil) + .function(backendMetaDataUtil::calculateApiVersion) + .whenInvokedWith(any(), any(), any(), any()) + .thenReturn(result) + return this + } + + fun arrange() = this to customServerConfigRepository + + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigMapperTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigMapperTest.kt index a4b684d4646..3651f08760a 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigMapperTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigMapperTest.kt @@ -24,7 +24,6 @@ import com.wire.kalium.logic.configuration.server.ServerConfig import com.wire.kalium.logic.configuration.server.ServerConfigMapper import com.wire.kalium.logic.configuration.server.ServerConfigMapperImpl import com.wire.kalium.logic.configuration.server.toCommonApiVersionType -import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.util.stubs.newServerConfig import com.wire.kalium.logic.util.stubs.newServerConfigDTO import com.wire.kalium.logic.util.stubs.newServerConfigEntity @@ -49,7 +48,7 @@ class ServerConfigMapperTest { @BeforeTest fun setup() { - serverConfigMapper = ServerConfigMapperImpl(versionMapper, MapperProvider.idMapper()) + serverConfigMapper = ServerConfigMapperImpl(versionMapper) given(versionMapper).invocation { toDTO(SERVER_CONFIG_TEST.metaData.commonApiVersion) }.then { ApiVersionDTO.Valid(1) } } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigRepositoryTest.kt index 901a74b05c4..7d45193396d 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/configuration/ServerConfigRepositoryTest.kt @@ -23,13 +23,11 @@ import com.wire.kalium.logic.configuration.server.ServerConfig import com.wire.kalium.logic.configuration.server.ServerConfigDataSource import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.failure.ServerConfigFailure -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.logic.util.stubs.newServerConfig import com.wire.kalium.logic.util.stubs.newServerConfigDTO import com.wire.kalium.logic.util.stubs.newServerConfigEntity -import com.wire.kalium.network.BackendMetaDataUtil import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi import com.wire.kalium.network.api.base.unbound.versioning.VersionApi import com.wire.kalium.network.tools.ApiVersionDTO @@ -46,106 +44,13 @@ import io.mockative.mock import io.mockative.once import io.mockative.verify import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertIs @ExperimentalCoroutinesApi class ServerConfigRepositoryTest { - - @Test - fun givenUrl_whenFetchingServerConfigSuccess_thenTheSuccessIsReturned() = runTest { - val (arrangement, repository) = Arrangement().withSuccessConfigResponse().arrange() - val expected = arrangement.SERVER_CONFIG.links - val serverConfigUrl = arrangement.SERVER_CONFIG_URL - - val actual = repository.fetchRemoteConfig(serverConfigUrl) - - actual.shouldSucceed { assertEquals(expected, it) } - verify(arrangement.serverConfigApi) - .coroutine { arrangement.serverConfigApi.fetchServerConfig(serverConfigUrl) } - .wasInvoked(exactly = once) - } - - @Test - fun givenStoredConfig_thenItCanBeRetrievedAsList() = runTest { - val (arrangement, repository) = Arrangement().withDaoEntityResponse().arrange() - val expected = listOf(newServerConfig(1), newServerConfig(2), newServerConfig(3)) - - repository.configList().shouldSucceed { assertEquals(it, expected) } - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::allConfig) - .wasInvoked(exactly = once) - } - - @Test - fun givenStoredConfig_thenItCanBeRetrievedAsFlow() = runTest { - val (arrangement, repository) = Arrangement().withDaoEntityFlowResponse().arrange() - val expected = listOf(newServerConfig(1), newServerConfig(2), newServerConfig(3)) - - val actual = repository.configFlow() - - assertIs>>>(actual) - assertEquals(expected.first(), actual.value.first()[0]) - - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::allConfigFlow) - .wasInvoked(exactly = once) - } - - @Test - fun givenStoredConfig_thenItCanBeRetrievedById() = runTest { - val (arrangement, repository) = Arrangement() - .withConfigById(newServerConfigEntity(1)) - .arrange() - val expected = newServerConfig(1) - - val actual = repository.configById(expected.id) - assertIs>(actual) - assertEquals(expected, actual.value) - - verify(arrangement.serverConfigDAO) - .function(arrangement.serverConfigDAO::configById) - .with(any()) - .wasInvoked(exactly = once) - } - - @Test - fun givenStoredConfig_thenItCanBeDeleted() = runTest { - val serverConfigId = "1" - val (arrangement, repository) = Arrangement() - .withConfigById(newServerConfigEntity(1)) - .arrange() - - val actual = repository.deleteById(serverConfigId) - - actual.shouldSucceed() - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::deleteById) - .with(any()) - .wasInvoked(exactly = once) - } - - @Test - fun givenStoredConfig_whenDeleting_thenItCanBeDeleted() = runTest { - val serverConfig = newServerConfig(1) - val (arrangement, repository) = Arrangement() - .withConfigById(newServerConfigEntity(1)) - .arrange() - - val actual = repository.delete(serverConfig) - - actual.shouldSucceed() - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::deleteById) - .with(any()) - .wasInvoked(exactly = once) - } - @Test fun givenValidCompatibleApiVersion_whenStoringConfigLocally_thenConfigIsStored() = runTest { val expected = newServerConfig(1) @@ -279,51 +184,6 @@ class ServerConfigRepositoryTest { .wasInvoked(exactly = once) } - @Test - fun givenStoredConfigLinksAndVersionInfoData_whenAddingNewOne_thenCommonApiShouldBeCalculatedAndConfigShouldBeStored() = runTest { - val expectedServerConfig = newServerConfig(1) - val expectedServerConfigDTO = newServerConfigDTO(1) - val expectedVersionInfo = ServerConfig.VersionInfo( - expectedServerConfig.metaData.federation, - listOf(expectedServerConfig.metaData.commonApiVersion.version), - expectedServerConfig.metaData.domain, - null - ) - val (arrangement, repository) = Arrangement() - .withConfigForNewRequest(newServerConfigEntity(1)) - .withCalculateApiVersion(expectedServerConfigDTO.metaData) - .arrange() - - repository - .storeConfig(expectedServerConfig.links, expectedVersionInfo) - .shouldSucceed { assertEquals(it, expectedServerConfig) } - - verify(arrangement.backendMetaDataUtil) - .function(arrangement.backendMetaDataUtil::calculateApiVersion) - .with(any(), any(), any(), any()) - .wasInvoked(exactly = once) - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::configByLinks) - .with(any()) - .wasInvoked(exactly = once) - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::insert) - .with(any()) - .wasInvoked(exactly = once) - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::updateApiVersion) - .with(any(), any()) - .wasNotInvoked() - verify(arrangement.serverConfigDAO) - .suspendFunction(arrangement.serverConfigDAO::setFederationToTrue) - .with(any()) - .wasNotInvoked() - verify(arrangement.serverConfigDAO) - .function(arrangement.serverConfigDAO::configById) - .with(any()) - .wasInvoked(exactly = once) - } - private class Arrangement { val SERVER_CONFIG_URL = "https://test.test/test.json" val SERVER_CONFIG_RESPONSE = newServerConfigDTO(1) @@ -340,11 +200,8 @@ class ServerConfigRepositoryTest { @Mock val versionApi = mock(classOf()) - @Mock - val backendMetaDataUtil = mock(classOf()) - private var serverConfigRepository: ServerConfigRepository = - ServerConfigDataSource(serverConfigApi, serverConfigDAO, versionApi, true, backendMetaDataUtil) + ServerConfigDataSource(serverConfigDAO, versionApi) val serverConfigEntity = newServerConfigEntity(1) val expectedServerConfig = newServerConfig(1).copy( @@ -429,14 +286,6 @@ class ServerConfigRepositoryTest { return this } - fun withCalculateApiVersion(result: ServerConfigDTO.MetaData): Arrangement { - given(backendMetaDataUtil) - .function(backendMetaDataUtil::calculateApiVersion) - .whenInvokedWith(any(), any(), any(), any()) - .thenReturn(result) - return this - } - fun arrange() = this to serverConfigRepository } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/id/FederatedIdMapperTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/id/FederatedIdMapperTest.kt index ca321580fc9..86ac4248972 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/id/FederatedIdMapperTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/id/FederatedIdMapperTest.kt @@ -35,7 +35,7 @@ import kotlin.test.assertEquals class FederatedIdMapperTest { - lateinit var federatedIdMapper: FederatedIdMapper + private lateinit var federatedIdMapper: FederatedIdMapper @Mock private val sessionRepository = mock(classOf()) @@ -57,7 +57,7 @@ class FederatedIdMapperTest { @Test fun givenAUserId_whenCurrentEnvironmentIsFederated_thenShouldMapTheValueWithDomain() = runTest { given(sessionRepository) - .function(sessionRepository::isFederated) + .suspendFunction(sessionRepository::isFederated) .whenInvokedWith(any()) .then { Either.Right(true) } @@ -69,7 +69,7 @@ class FederatedIdMapperTest { @Test fun givenAUserId_whenCurrentEnvironmentIsNotFederated_thenShouldMapTheValueWithoutDomain() = runTest { given(sessionRepository) - .function(sessionRepository::isFederated) + .suspendFunction(sessionRepository::isFederated) .whenInvokedWith(any()) .then { Either.Right(false) } @@ -81,7 +81,7 @@ class FederatedIdMapperTest { @Test fun givenError_whenGettingUserFederationStatus_thenShouldMapTheValueWithoutDomain() = runTest { given(sessionRepository) - .function(sessionRepository::isFederated) + .suspendFunction(sessionRepository::isFederated) .whenInvokedWith(any()) .then { Either.Left(StorageFailure.Generic(IOException("why are we still here just to suffer!"))) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionMapperTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionMapperTest.kt index 0d9be02d497..0fee004c12b 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionMapperTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionMapperTest.kt @@ -18,7 +18,6 @@ package com.wire.kalium.logic.data.session -import com.wire.kalium.logic.data.id.IdMapper import com.wire.kalium.logic.data.user.SsoId import com.wire.kalium.logic.data.user.UserId import com.wire.kalium.logic.data.auth.AccountTokens @@ -26,10 +25,6 @@ import com.wire.kalium.network.api.base.model.SessionDTO import com.wire.kalium.persistence.client.AuthTokenEntity import com.wire.kalium.persistence.dao.UserIDEntity import com.wire.kalium.persistence.model.SsoIdEntity -import io.mockative.Mock -import io.mockative.classOf -import io.mockative.given -import io.mockative.mock import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals @@ -37,14 +32,11 @@ import com.wire.kalium.network.api.base.model.UserId as UserIdDTO class SessionMapperTest { - @Mock - val idMapper = mock(classOf()) - private lateinit var sessionMapper: SessionMapper @BeforeTest fun setup() { - sessionMapper = SessionMapperImpl(idMapper) + sessionMapper = SessionMapperImpl() } @Test @@ -70,8 +62,6 @@ class SessionMapperTest { fun givenAnAuthTokens_whenMappingToPersistenceAuthTokens_thenValuesAreMappedCorrectly() { val authSession: AccountTokens = TEST_AUTH_TOKENS - given(idMapper).invocation { idMapper.toSsoIdEntity(TEST_SSO_ID) }.then { TEST_SSO_ID_ENTITY } - val expected: AuthTokenEntity = with(authSession) { AuthTokenEntity( userId = UserIDEntity(userId.value, userId.domain), diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionRepositoryTest.kt index 26427538260..ee72ae39b6e 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/session/SessionRepositoryTest.kt @@ -18,13 +18,13 @@ package com.wire.kalium.logic.data.session -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.featureFlags.KaliumConfigs import com.wire.kalium.persistence.client.AuthTokenStorage import com.wire.kalium.persistence.dao.UserIDEntity import com.wire.kalium.persistence.daokaliumdb.AccountInfoEntity import com.wire.kalium.persistence.daokaliumdb.AccountsDAO +import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO import io.mockative.Mock import io.mockative.given import io.mockative.mock @@ -78,7 +78,6 @@ class SessionRepositoryTest { private class Arrangement { val sessionMapper = MapperProvider.sessionMapper() - val idMapper = MapperProvider.idMapper() @Mock val accountsDAO: AccountsDAO = mock(AccountsDAO::class) @@ -90,10 +89,10 @@ class SessionRepositoryTest { val kaliumConfigs: KaliumConfigs = mock(KaliumConfigs::class) @Mock - val serverConfigRepository: ServerConfigRepository = mock(ServerConfigRepository::class) + val serverConfigurationDAO: ServerConfigurationDAO = mock(ServerConfigurationDAO::class) private val sessionRepository = - SessionDataSource(accountsDAO, authTokenStorage, serverConfigRepository, kaliumConfigs, sessionMapper, idMapper) + SessionDataSource(accountsDAO, authTokenStorage, serverConfigurationDAO, kaliumConfigs) val validAccountIndoEntity = AccountInfoEntity(userIDEntity = UserIDEntity("1", "domain"), null) diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCaseTest.kt index 9ba3b9e48d1..9963c007156 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/AddAuthenticatedUserUseCaseTest.kt @@ -20,18 +20,22 @@ package com.wire.kalium.logic.feature.auth import com.wire.kalium.logic.StorageFailure import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.data.auth.Account import com.wire.kalium.logic.data.auth.AccountInfo import com.wire.kalium.logic.data.auth.AccountTokens import com.wire.kalium.logic.data.auth.login.ProxyCredentials +import com.wire.kalium.logic.data.id.toDao import com.wire.kalium.logic.data.session.SessionRepository import com.wire.kalium.logic.data.session.token.AccessToken import com.wire.kalium.logic.data.session.token.RefreshToken import com.wire.kalium.logic.data.user.SsoId import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.util.stubs.newServerConfig +import com.wire.kalium.persistence.dao.UserIDEntity +import com.wire.kalium.persistence.daokaliumdb.ServerConfigurationDAO +import com.wire.kalium.persistence.model.ServerConfigEntity import io.mockative.Mock import io.mockative.any import io.mockative.given @@ -116,12 +120,13 @@ class AddAuthenticatedUserUseCaseTest { val proxyCredentials = PROXY_CREDENTIALS + val (arrangement, addAuthenticatedUserUseCase) = Arrangement() .withDoesValidSessionExistResult(newSession.userId, Either.Right(true)) .withStoreSessionResult(TEST_SERVER_CONFIG.id, TEST_SSO_ID, newSession, proxyCredentials, Either.Right(Unit)) .withUpdateCurrentSessionResult(newSession.userId, Either.Right(Unit)) .withFullAccountInfoResult(newSession.userId, Either.Right(oldSessionFullInfo)) - .withConfigByIdResult(TEST_SERVER_CONFIG.id, Either.Right(TEST_SERVER_CONFIG)) + .withConfigByIdSuccess(TEST_SERVER_CONFIG.id, TEST_SERVER_CONFIG_ENTITY) .arrange() val actual = addAuthenticatedUserUseCase(TEST_SERVER_CONFIG.id, TEST_SSO_ID, newSession, proxyCredentials, true) @@ -138,8 +143,8 @@ class AddAuthenticatedUserUseCaseTest { .with(any()) .wasInvoked(exactly = once) - verify(arrangement.serverConfigRepository) - .function(arrangement.serverConfigRepository::configById) + verify(arrangement.serverConfigurationDAO) + .function(arrangement.serverConfigurationDAO::configById) .with(any()) .wasInvoked(exactly = once) @@ -155,24 +160,32 @@ class AddAuthenticatedUserUseCaseTest { @Test fun givenUserWithAlreadyStoredSessionWithDifferentServerConfig_whenInvokedWithReplace_thenUserAlreadyExistsReturned() = runTest { + val serverConfigMapper = MapperProvider.serverConfigMapper() + val oldSession = TEST_AUTH_TOKENS.copy( accessToken = AccessToken("oldAccessToken", TEST_AUTH_TOKENS.tokenType), refreshToken = RefreshToken("oldRefreshToken") ) val oldSessionServer = newServerConfig(id = 11) + val oldSessionServerEntity = oldSessionServer.let { + serverConfigMapper.toEntity(it) + } val newSession = TEST_AUTH_TOKENS.copy( accessToken = AccessToken("newAccessToken", TEST_AUTH_TOKENS.tokenType), refreshToken = RefreshToken("newRefreshToken") ) val newSessionServer = newServerConfig(id = 22) + val newSessionServerEntity = newSessionServer.let { + serverConfigMapper.toEntity(it) + } val proxyCredentials = PROXY_CREDENTIALS val (arrangement, addAuthenticatedUserUseCase) = Arrangement() .withDoesValidSessionExistResult(newSession.userId, Either.Right(true)) - .withConfigForUserIdResult(oldSession.userId, Either.Right(oldSessionServer)) - .withConfigByIdResult(newSessionServer.id, Either.Right(newSessionServer)) + .withConfigForUserIdSuccess(oldSession.userId.toDao(), oldSessionServerEntity) + .withConfigByIdSuccess(newSessionServer.id, newSessionServerEntity) .withFullAccountInfoResult( oldSession.userId, Either.Right(Account(AccountInfo.Valid(oldSession.userId), oldSessionServer, TEST_SSO_ID)) @@ -198,14 +211,17 @@ class AddAuthenticatedUserUseCaseTest { verify(arrangement.sessionRepository) .function(arrangement.sessionRepository::fullAccountInfo).with(any()) .wasInvoked(exactly = once) - verify(arrangement.serverConfigRepository) - .function(arrangement.serverConfigRepository::configById).with(any()) + verify(arrangement.serverConfigurationDAO) + .function(arrangement.serverConfigurationDAO::configById).with(any()) .wasInvoked(exactly = once) } private companion object { val TEST_USERID = UserId("user_id", "domain.de") val TEST_SERVER_CONFIG: ServerConfig = newServerConfig(1) + val TEST_SERVER_CONFIG_ENTITY = TEST_SERVER_CONFIG.let { + MapperProvider.serverConfigMapper().toEntity(it) + } val TEST_AUTH_TOKENS = AccountTokens( TEST_USERID, "access-token", @@ -226,9 +242,9 @@ class AddAuthenticatedUserUseCaseTest { val sessionRepository = mock(SessionRepository::class) @Mock - val serverConfigRepository = mock(ServerConfigRepository::class) + val serverConfigurationDAO = mock(ServerConfigurationDAO::class) - private val addAuthenticatedUserUseCase = AddAuthenticatedUserUseCase(sessionRepository, serverConfigRepository) + private val addAuthenticatedUserUseCase = AddAuthenticatedUserUseCase(sessionRepository, serverConfigurationDAO) suspend fun withDoesValidSessionExistResult( userId: UserId, @@ -237,11 +253,11 @@ class AddAuthenticatedUserUseCaseTest { given(sessionRepository).coroutine { doesValidSessionExist(userId) }.then { result } } - suspend fun withConfigForUserIdResult( - userId: UserId, - result: Either + suspend fun withConfigForUserIdSuccess( + userId: UserIDEntity, + result: ServerConfigEntity ) = apply { - given(serverConfigRepository).coroutine { configForUser(userId) }.then { result } + given(serverConfigurationDAO).coroutine { configForUser(userId) }.then { result } } fun withFullAccountInfoResult( @@ -251,11 +267,11 @@ class AddAuthenticatedUserUseCaseTest { given(sessionRepository).invocation { fullAccountInfo(userId) }.then { result } } - fun withConfigByIdResult( + fun withConfigByIdSuccess( serverConfigId: String, - result: Either + result: ServerConfigEntity ) = apply { - given(serverConfigRepository).invocation { configById(serverConfigId) }.then { result } + given(serverConfigurationDAO).invocation { configById(serverConfigId) }.then { result } } suspend fun withStoreSessionResult( diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCaseTest.kt index 1935828c462..eafa07f6d8d 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/auth/DomainLookupUseCaseTest.kt @@ -18,12 +18,17 @@ package com.wire.kalium.logic.feature.auth import com.wire.kalium.logic.NetworkFailure +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.data.auth.login.DomainLookupResult import com.wire.kalium.logic.data.auth.login.SSOLoginRepository +import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.util.stubs.newServerConfig +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.exceptions.KaliumException +import com.wire.kalium.network.tools.ServerConfigDTO +import com.wire.kalium.network.utils.NetworkResponse import io.mockative.Mock import io.mockative.any import io.mockative.eq @@ -38,7 +43,6 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertIs -@OptIn(ExperimentalCoroutinesApi::class) class DomainLookupUseCaseTest { @Test @@ -79,8 +83,8 @@ class DomainLookupUseCaseTest { .arrange() useCases(userEmail) - verify(arrangement.serverConfigRepository) - .suspendFunction(arrangement.serverConfigRepository::fetchRemoteConfig) + verify(arrangement.customServerConfigRepository) + .suspendFunction(arrangement.customServerConfigRepository::fetchRemoteConfig) .with(eq("https://wire.com")) .wasInvoked(exactly = once) } @@ -89,6 +93,7 @@ class DomainLookupUseCaseTest { fun givenSuccess_whenLookup_thenSuccessIsPropagated() = runTest { val userEmail = "cool-person@wire.com" val expectedServerLinks = newServerConfig(1).links + val (arrangement, useCases) = Arrangement() .withDomainLookupResult(Either.Right(DomainLookupResult("https://wire.com", "https://wire.com"))) .withFetchServerConfigResult(Either.Right(expectedServerLinks)) @@ -104,8 +109,8 @@ class DomainLookupUseCaseTest { .with(eq("wire.com")) .wasInvoked(exactly = once) - verify(arrangement.serverConfigRepository) - .suspendFunction(arrangement.serverConfigRepository::fetchRemoteConfig) + verify(arrangement.customServerConfigRepository) + .suspendFunction(arrangement.customServerConfigRepository::fetchRemoteConfig) .with(eq("https://wire.com")) .wasInvoked(exactly = once) } @@ -116,10 +121,10 @@ class DomainLookupUseCaseTest { val ssoLoginRepository: SSOLoginRepository = mock(SSOLoginRepository::class) @Mock - val serverConfigRepository: ServerConfigRepository = mock(ServerConfigRepository::class) + val customServerConfigRepository: CustomServerConfigRepository = mock(CustomServerConfigRepository::class) private val useCases = DomainLookupUseCase( - serverConfigRepository, + customServerConfigRepository, ssoLoginRepository ) @@ -130,9 +135,10 @@ class DomainLookupUseCaseTest { .thenReturn(result) } - fun withFetchServerConfigResult(result: Either) = apply { - given(serverConfigRepository) - .suspendFunction(serverConfigRepository::fetchRemoteConfig) + fun withFetchServerConfigResult(result: + Either) = apply { + given(customServerConfigRepository) + .suspendFunction(customServerConfigRepository::fetchRemoteConfig) .whenInvokedWith(any()) .thenReturn(result) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/ObserveNewClientsUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/ObserveNewClientsUseCaseTest.kt index 160b8eec649..da570879e47 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/ObserveNewClientsUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/ObserveNewClientsUseCaseTest.kt @@ -100,7 +100,7 @@ class ObserveNewClientsUseCaseTest { ) verify(arrangement.observeValidAccounts) - .function(arrangement.observeValidAccounts::invoke) + .suspendFunction(arrangement.observeValidAccounts::invoke) .wasInvoked(exactly = once) awaitComplete() @@ -211,7 +211,7 @@ class ObserveNewClientsUseCaseTest { init { given(observeValidAccounts) - .function(observeValidAccounts::invoke) + .suspendFunction(observeValidAccounts::invoke) .whenInvoked() .thenReturn(flowOf(listOf())) @@ -250,13 +250,13 @@ class ObserveNewClientsUseCaseTest { fun withValidAccounts(result: List>) = apply { given(observeValidAccounts) - .function(observeValidAccounts::invoke) + .suspendFunction(observeValidAccounts::invoke) .whenInvoked() .thenReturn(flowOf(result)) } fun withValidAccountsFlow(flowResult: Flow>>) = apply { given(observeValidAccounts) - .function(observeValidAccounts::invoke) + .suspendFunction(observeValidAccounts::invoke) .whenInvoked() .thenReturn(flowResult) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCaseTest.kt index e458aa7d867..f1fe4efb051 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/featureConfig/ObserveIsAppLockEditableUseCaseTest.kt @@ -116,7 +116,7 @@ class ObserveIsAppLockEditableUseCaseTest { fun arrange() = this to useCase fun withAllValidSessionsFlow(result: Flow>) = apply { given(sessionRepository) - .function(sessionRepository::allValidSessionsFlow) + .suspendFunction(sessionRepository::allValidSessionsFlow) .whenInvoked() .thenReturn(result.map { Either.Right(it) }) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/FetchApiVersionUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/FetchApiVersionUseCaseTest.kt deleted file mode 100644 index 195738b52eb..00000000000 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/FetchApiVersionUseCaseTest.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.feature.server - -import com.wire.kalium.logic.CoreFailure -import com.wire.kalium.logic.configuration.server.CommonApiVersionType -import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository -import com.wire.kalium.logic.failure.ServerConfigFailure -import com.wire.kalium.logic.functional.Either -import io.mockative.Mock -import io.mockative.any -import io.mockative.classOf -import io.mockative.given -import io.mockative.mock -import io.mockative.once -import io.mockative.verify -import kotlinx.coroutines.test.runTest -import kotlin.test.Test -import kotlin.test.assertEquals - -class FetchApiVersionUseCaseTest { - - @Test - fun givenASuccessfulRepositoryResponse_whenInvokingTheUseCase_thenSuccessResultIsReturned() = runTest { - // Given - val serverConfig = ServerConfig( - "", - ServerConfig.DEFAULT, - ServerConfig.MetaData(false, CommonApiVersionType.New, "") - ) - - val (arrangement, fetchApiVersionUseCase) = Arrangement() - .withSuccessfulResponse(serverConfig) - .arrange() - - // When - fetchApiVersionUseCase.invoke(serverConfig.links) - - // Then - verify(arrangement.configRepository) - .suspendFunction(arrangement.configRepository::fetchApiVersionAndStore).with(any()) - .wasInvoked(exactly = once) - } - - @Test - fun givenRepositoryCallFailWithNewServerVersion_thenTooNewVersionIsReturned() = runTest { - // Given - val newServerVersionFail = ServerConfigFailure.NewServerVersion - val serverConfig = ServerConfig( - "", - ServerConfig.DEFAULT, - ServerConfig.MetaData(false, CommonApiVersionType.New, "") - ) - - val (arrangement, fetchApiVersionUseCase) = Arrangement() - .withErrorResponse(newServerVersionFail) - .arrange() - - // When - val result = fetchApiVersionUseCase.invoke(serverConfig.links) - - // Then - verify(arrangement.configRepository) - .suspendFunction(arrangement.configRepository::fetchApiVersionAndStore).with(any()) - .wasInvoked(exactly = once) - - assertEquals(result, FetchApiVersionResult.Failure.TooNewVersion) - } - - @Test - fun givenRepositoryCallFailWithUnknownServerVersion_thenUnknownServerVersionIsReturned() = runTest { - // Given - val unknownServerVersionFail = ServerConfigFailure.UnknownServerVersion - val serverConfig = ServerConfig( - "", - ServerConfig.DEFAULT, - ServerConfig.MetaData(false, CommonApiVersionType.New, "") - ) - - val (arrangement, fetchApiVersionUseCase) = Arrangement() - .withErrorResponse(unknownServerVersionFail) - .arrange() - - // When - val result = fetchApiVersionUseCase.invoke(serverConfig.links) - - // Then - verify(arrangement.configRepository) - .suspendFunction(arrangement.configRepository::fetchApiVersionAndStore).with(any()) - .wasInvoked(exactly = once) - - assertEquals(result, FetchApiVersionResult.Failure.UnknownServerVersion) - } - - private class Arrangement { - - @Mock - val configRepository = mock(classOf()) - - val fetchApiVersionUseCase = FetchApiVersionUseCaseImpl(configRepository) - - fun withSuccessfulResponse(serverConfig: ServerConfig): Arrangement { - given(configRepository) - .suspendFunction(configRepository::fetchApiVersionAndStore).whenInvokedWith(any()) - .thenReturn(Either.Right(serverConfig)) - return this - } - - fun withErrorResponse(coreFailure: CoreFailure): Arrangement { - given(configRepository) - .suspendFunction(configRepository::fetchApiVersionAndStore).whenInvokedWith(any()) - .thenReturn(Either.Left(coreFailure)) - return this - } - - fun arrange() = this to fetchApiVersionUseCase - } -} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCaseTest.kt index 12494ff3ecb..0c667d6690a 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/StoreServerConfigUseCaseTest.kt @@ -19,8 +19,8 @@ package com.wire.kalium.logic.feature.server import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.configuration.server.CustomServerConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfig -import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.util.stubs.newServerConfig import io.mockative.Mock @@ -54,8 +54,8 @@ class StoreServerConfigUseCaseTest { assertEquals(expected, it.serverConfig) } - verify(arrangement.configRepository) - .coroutine { arrangement.configRepository.storeConfig(links, versionInfo) } + verify(arrangement.customServerConfigRepository) + .coroutine { arrangement.customServerConfigRepository.storeConfig(links, versionInfo) } .wasInvoked(exactly = once) } @@ -74,24 +74,24 @@ class StoreServerConfigUseCaseTest { assertEquals(expected, it.serverConfig) } - verify(arrangement.configRepository) - .coroutine { arrangement.configRepository.storeConfig(expected.links, versionInfo) } + verify(arrangement.customServerConfigRepository) + .coroutine { arrangement.customServerConfigRepository.storeConfig(expected.links, versionInfo) } .wasInvoked(exactly = once) } private class Arrangement { @Mock - val configRepository = mock(ServerConfigRepository::class) - private val useCase = StoreServerConfigUseCaseImpl(configRepository) + val customServerConfigRepository = mock(CustomServerConfigRepository::class) + private val useCase = StoreServerConfigUseCaseImpl(customServerConfigRepository) suspend fun withStoreConfig( links: ServerConfig.Links, versionInfo: ServerConfig.VersionInfo, result: Either ) = apply { - given(configRepository) + given(customServerConfigRepository) .suspendFunction( - configRepository::storeConfig, + customServerConfigRepository::storeConfig, fun2()) .whenInvokedWith(eq(links), eq(versionInfo)) .thenReturn(result) diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionUseCaseTest.kt index 129365f1a25..0ede23e68d4 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/server/UpdateApiVersionUseCaseTest.kt @@ -18,56 +18,299 @@ package com.wire.kalium.logic.feature.server +import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.configuration.server.ServerConfig import com.wire.kalium.logic.configuration.server.ServerConfigRepository +import com.wire.kalium.logic.data.auth.login.ProxyCredentials +import com.wire.kalium.logic.data.id.toDao +import com.wire.kalium.logic.data.session.SessionRepository +import com.wire.kalium.logic.data.user.UserId import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.util.stubs.newServerConfig +import com.wire.kalium.persistence.client.AuthTokenStorage +import com.wire.kalium.persistence.client.ProxyCredentialsEntity +import com.wire.kalium.persistence.dao.UserIDEntity import io.mockative.Mock -import io.mockative.Times import io.mockative.any -import io.mockative.configure +import io.mockative.eq import io.mockative.given -import io.mockative.matchers.OneOfMatcher import io.mockative.mock +import io.mockative.once import io.mockative.verify import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest -import kotlin.test.BeforeTest +import okio.IOException import kotlin.test.Test +import kotlin.test.assertEquals @OptIn(ExperimentalCoroutinesApi::class) class UpdateApiVersionUseCaseTest { - @Mock - internal val configRepository = configure(mock(ServerConfigRepository::class)) { stubsUnitByDefault = true } + @Test + fun givenError_whenCallingValidSessionsWithServerConfig_thenDoNothingElse() { + val (arrangement, updateApiVersionsUseCase) = Arrangement() + .arrange { + withValidSessionWithServerConfig(Either.Left(StorageFailure.Generic(IOException()))) + } + + runTest { + updateApiVersionsUseCase() + advanceUntilIdle() + } + + assertEquals(0, arrangement.serverConfigProviderCalledCount) + } + + @Test + fun givenUsersWithServerConfigNoProxy_thenDoNotFetchProxyCredentials() { + val (arrangement, updateApiVersionsUseCase) = Arrangement() + .arrange { + withValidSessionWithServerConfig( + Either.Right( + mapOf( + userId1 to serverConfig1.copy( + links = serverConfig1.links.copy( + apiProxy = null + ) + ) + ) + ) + ) + withUpdateConfigApiVersion(serverConfig1, Either.Right(Unit)) + } + + runTest { + updateApiVersionsUseCase() + advanceUntilIdle() + } + + verify(arrangement.tokenStorage) + .suspendFunction(arrangement.tokenStorage::proxyCredentials) + .with(any()) + .wasNotInvoked() + + + verify(arrangement.serverConfigRepository1) + .suspendFunction(arrangement.serverConfigRepository1::updateConfigApiVersion) + .with(eq(serverConfig1)) + .wasInvoked(exactly = once) + } + + @Test + fun givenUserWithProxyButNoAuthentication_thenDoNotFetchProxyCredentials() { + val (arrangement, updateApiVersionsUseCase) = Arrangement() + .arrange { + withValidSessionWithServerConfig( + Either.Right( + mapOf( + userId1 to serverConfig1.copy( + links = serverConfig1.links.copy( + apiProxy = ServerConfig.ApiProxy( + host = "host", + port = 1234, + needsAuthentication = false + ) + ) + ) + ) + ) + ) + withUpdateConfigApiVersion(serverConfig1, Either.Right(Unit)) + } + + runTest { + updateApiVersionsUseCase() + advanceUntilIdle() + } + + verify(arrangement.tokenStorage) + .suspendFunction(arrangement.tokenStorage::proxyCredentials) + .with(any()) + .wasNotInvoked() + + + verify(arrangement.serverConfigRepository1) + .suspendFunction(arrangement.serverConfigRepository1::updateConfigApiVersion) + .with(any()) + .wasInvoked(exactly = once) + } + + @Test + fun givenUserWithProxyAndNeedAuthentication_thenFetchProxyCredentials() { + val (arrangement, updateApiVersionsUseCase) = Arrangement() + .arrange { + withValidSessionWithServerConfig( + Either.Right( + mapOf( + userId1 to serverConfig1.copy( + links = serverConfig1.links.copy( + apiProxy = ServerConfig.ApiProxy( + host = "host", + port = 1234, + needsAuthentication = true + ) + ) + ) + ) + ) + ) + withUpdateConfigApiVersion(serverConfig1, Either.Right(Unit)) + withProxyCredForUser(userId1.toDao(), ProxyCredentialsEntity("user", "pass")) + } + + runTest { + updateApiVersionsUseCase() + advanceUntilIdle() + } - private lateinit var updateApiVersionsUseCase: UpdateApiVersionsUseCase + assertEquals(1, arrangement.serverConfigProviderCalledCount) + verify(arrangement.tokenStorage) + .suspendFunction(arrangement.tokenStorage::proxyCredentials) + .with(any()) + .wasInvoked(exactly = once) - @BeforeTest - fun setup() { - updateApiVersionsUseCase = UpdateApiVersionsUseCaseImpl(configRepository) + verify(arrangement.serverConfigRepository1) + .suspendFunction(arrangement.serverConfigRepository1::updateConfigApiVersion) + .with(any()) + .wasInvoked(exactly = once) } @Test - fun givenConfigList_whenUpdatingApiVersions_thenALLMUSTBEUPDATED() = runTest { - val configList = listOf(newServerConfig(1), newServerConfig(2), newServerConfig(3), newServerConfig(4)) - - given(configRepository) - .suspendFunction(configRepository::configList) - .whenInvoked() - .thenReturn( - Either.Right(configList) - ) - - given(configRepository) - .suspendFunction(configRepository::updateConfigApiVersion) - .whenInvokedWith(any()) - .then { Either.Right(Unit) } - - updateApiVersionsUseCase() - - verify(configRepository) - .suspendFunction(configRepository::updateConfigApiVersion) - .with(OneOfMatcher(configList.map { it.id })) - .wasInvoked(exactly = Times(configList.size)) + fun givenMultipleUsers_thenUpdateApiVersionForAll() { + val (arrangement, updateApiVersionsUseCase) = Arrangement() + .arrange { + withValidSessionWithServerConfig( + Either.Right( + mapOf( + userId1 to serverConfig1.copy( + links = serverConfig1.links.copy( + apiProxy = ServerConfig.ApiProxy( + host = "host", + port = 1234, + needsAuthentication = false + ) + ) + ), + userId2 to serverConfig2.copy( + links = serverConfig2.links.copy( + apiProxy = ServerConfig.ApiProxy( + host = "host", + port = 1234, + needsAuthentication = true + ) + ) + ) + ) + ) + ) + withUpdateConfigApiVersion(serverConfig1, Either.Right(Unit)) + withUpdateConfigApiVersion(serverConfig2, Either.Right(Unit)) + withProxyCredForUser(userId2.toDao(), ProxyCredentialsEntity("user", "pass")) + } + + runTest { + updateApiVersionsUseCase() + advanceUntilIdle() + } + + assertEquals(2, arrangement.serverConfigProviderCalledCount) + verify(arrangement.tokenStorage) + .suspendFunction(arrangement.tokenStorage::proxyCredentials) + .with(eq(userId2.toDao())) + .wasInvoked(exactly = once) + + verify(arrangement.tokenStorage) + .suspendFunction(arrangement.tokenStorage::proxyCredentials) + .with(eq(userId1.toDao())) + .wasNotInvoked() + + verify(arrangement.serverConfigRepository1) + .suspendFunction(arrangement.serverConfigRepository1::updateConfigApiVersion) + .with(any()) + .wasInvoked(exactly = once) + + verify(arrangement.serverConfigRepository2) + .suspendFunction(arrangement.serverConfigRepository2::updateConfigApiVersion) + .with(any()) + .wasInvoked(exactly = once) + + } + private companion object { + val userId1: UserId = UserId("user1", "domnaion1") + val userId2: UserId = UserId("user2", "domnaion2") + val serverConfig1 = newServerConfig(1) + val serverConfig2 = newServerConfig(2) + } + + private class Arrangement { + @Mock + val sessionRepository: SessionRepository = mock(SessionRepository::class) + + @Mock + val tokenStorage: AuthTokenStorage = mock(AuthTokenStorage::class) + + var serverConfigProviderCalledCount: Int = 0 + private set + + @Mock + val serverConfigRepository1: ServerConfigRepository = mock(ServerConfigRepository::class) + + @Mock + val serverConfigRepository2: ServerConfigRepository = mock(ServerConfigRepository::class) + + fun withProxyCredForUser( + userId: UserIDEntity, + result: ProxyCredentialsEntity? + ) { + given(tokenStorage) + .function(tokenStorage::proxyCredentials) + .whenInvokedWith(eq(userId)) + .then { result } + } + + fun withUpdateConfigApiVersion( + serverConfig: ServerConfig, + result: Either + ) { + when (serverConfig.id) { + serverConfig1.id -> given(serverConfigRepository1) + .suspendFunction(serverConfigRepository1::updateConfigApiVersion) + .whenInvokedWith(any()) + .then { result } + + serverConfig2.id -> given(serverConfigRepository2) + .suspendFunction(serverConfigRepository2::updateConfigApiVersion) + .whenInvokedWith(any()) + .then { result } + + else -> throw IllegalArgumentException("Unexpected server config: $serverConfig") + } + } + + fun withValidSessionWithServerConfig( + result: Either> + ) { + given(sessionRepository) + .suspendFunction(sessionRepository::validSessionsWithServerConfig) + .whenInvoked() + .then { result } + } + + private val updateApiVersionsUseCase = UpdateApiVersionsUseCaseImpl( + sessionRepository, + tokenStorage, + { serverConfig: ServerConfig, proxyCredentials: ProxyCredentials? -> + serverConfigProviderCalledCount++ + when (serverConfig.id) { + serverConfig1.id -> serverConfigRepository1 + serverConfig2.id -> serverConfigRepository2 + else -> throw IllegalArgumentException("Unexpected server config: $serverConfig") + } + } + ) + + fun arrange(block: Arrangement.() -> Unit) = apply(block).let { this to updateApiVersionsUseCase } } } diff --git a/logic/src/jvmMain/kotlin/com/wire/kalium/logic/CoreLogic.kt b/logic/src/jvmMain/kotlin/com/wire/kalium/logic/CoreLogic.kt index 0d5508a850d..57b7dfebb7f 100644 --- a/logic/src/jvmMain/kotlin/com/wire/kalium/logic/CoreLogic.kt +++ b/logic/src/jvmMain/kotlin/com/wire/kalium/logic/CoreLogic.kt @@ -24,11 +24,11 @@ import com.wire.kalium.logic.feature.UserSessionScopeProvider import com.wire.kalium.logic.feature.UserSessionScopeProviderImpl import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs -import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.logic.network.NetworkStateObserverImpl import com.wire.kalium.logic.sync.GlobalWorkScheduler import com.wire.kalium.logic.sync.GlobalWorkSchedulerImpl import com.wire.kalium.logic.util.PlatformContext +import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider import kotlinx.coroutines.cancel @@ -74,6 +74,7 @@ actual class CoreLogic( kaliumConfigs, globalPreferences, globalCallManager, + globalDatabase, userStorageProvider, networkStateObserver, logoutCallbackManager, diff --git a/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt b/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt index ac56ebfab5d..739073e95e1 100644 --- a/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt +++ b/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt @@ -31,8 +31,9 @@ import com.wire.kalium.logic.feature.auth.AuthenticationScopeProvider import com.wire.kalium.logic.feature.auth.LogoutCallback import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs -import com.wire.kalium.network.NetworkStateObserver import com.wire.kalium.logic.sync.UserSessionWorkScheduler +import com.wire.kalium.network.NetworkStateObserver +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider @Suppress("LongParameterList") @@ -42,6 +43,7 @@ internal fun UserSessionScope( globalScope: GlobalKaliumScope, globalCallManager: GlobalCallManager, globalPreferences: GlobalPrefProvider, + globalDatabaseProvider: GlobalDatabaseProvider, authenticationScopeProvider: AuthenticationScopeProvider, userSessionWorkScheduler: UserSessionWorkScheduler, rootPathsProvider: RootPathsProvider, @@ -61,6 +63,7 @@ internal fun UserSessionScope( userId, globalScope, globalCallManager, + globalDatabaseProvider, globalPreferences, authenticationScopeProvider, userSessionWorkScheduler, diff --git a/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt b/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt index c838c85dbc3..3b7102ec406 100644 --- a/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt +++ b/logic/src/jvmMain/kotlin/com/wire/kalium/logic/feature/UserSessionScopeProviderImpl.kt @@ -35,6 +35,7 @@ import com.wire.kalium.logic.feature.call.GlobalCallManager import com.wire.kalium.logic.featureFlags.KaliumConfigs import com.wire.kalium.logic.sync.UserSessionWorkSchedulerImpl import com.wire.kalium.network.NetworkStateObserver +import com.wire.kalium.persistence.db.GlobalDatabaseProvider import com.wire.kalium.persistence.kmmSettings.GlobalPrefProvider import java.io.File @@ -46,6 +47,7 @@ internal actual class UserSessionScopeProviderImpl( private val kaliumConfigs: KaliumConfigs, private val globalPreferences: GlobalPrefProvider, private val globalCallManager: GlobalCallManager, + private val globalDatabaseProvider: GlobalDatabaseProvider, private val userStorageProvider: UserStorageProvider, private val networkStateObserver: NetworkStateObserver, private val logoutCallback: LogoutCallback, @@ -74,6 +76,7 @@ internal actual class UserSessionScopeProviderImpl( globalScope, globalCallManager, globalPreferences, + globalDatabaseProvider, authenticationScopeProvider, userSessionWorkScheduler, rootPathsProvider, diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/HttpEngine.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/HttpEngine.kt index f04cb69cf09..2e52dec38ca 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/HttpEngine.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/HttpEngine.kt @@ -24,8 +24,8 @@ import com.wire.kalium.network.tools.ServerConfigDTO import io.ktor.client.engine.HttpClientEngine expect fun defaultHttpEngine( - serverConfigDTOApiProxy: ServerConfigDTO.ApiProxy? = null, - proxyCredentials: ProxyCredentialsDTO? = null, + serverConfigDTOApiProxy: ServerConfigDTO.ApiProxy?, + proxyCredentials: ProxyCredentialsDTO?, ignoreSSLCertificates: Boolean = false, certificatePinning: CertificatePinning ): HttpClientEngine diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/configuration/ServerConfigApi.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/configuration/ServerConfigApi.kt index a914a18ad52..f3bde729893 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/configuration/ServerConfigApi.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/configuration/ServerConfigApi.kt @@ -18,6 +18,7 @@ package com.wire.kalium.network.api.base.unbound.configuration +import com.wire.kalium.network.UnauthenticatedNetworkClient import com.wire.kalium.network.UnboundNetworkClient import com.wire.kalium.network.exceptions.KaliumException import com.wire.kalium.network.tools.KtxSerializer @@ -27,22 +28,28 @@ import com.wire.kalium.network.utils.flatMap import com.wire.kalium.network.utils.mapSuccess import com.wire.kalium.network.utils.setUrl import com.wire.kalium.network.utils.wrapKaliumResponse +import io.ktor.client.HttpClient import io.ktor.client.request.accept import io.ktor.client.request.get import io.ktor.http.ContentType import io.ktor.http.Url import kotlinx.serialization.SerializationException -import kotlinx.serialization.decodeFromString interface ServerConfigApi { suspend fun fetchServerConfig(serverConfigUrl: String): NetworkResponse } class ServerConfigApiImpl internal constructor( - private val unboundNetworkClient: UnboundNetworkClient + private val httpClient: HttpClient ) : ServerConfigApi { - private val httpClient get() = unboundNetworkClient.httpClient + internal constructor(unauthenticatedNetworkClient: UnauthenticatedNetworkClient) : this( + httpClient = unauthenticatedNetworkClient.httpClient + ) + + internal constructor(unboundNetworkClient: UnboundNetworkClient) : this( + httpClient = unboundNetworkClient.httpClient + ) /** * Fetch remote configuration diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/versioning/VersionApi.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/versioning/VersionApi.kt index 8298b0533a4..e9a010e3504 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/versioning/VersionApi.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/api/base/unbound/versioning/VersionApi.kt @@ -20,7 +20,7 @@ package com.wire.kalium.network.api.base.unbound.versioning import com.wire.kalium.network.BackendMetaDataUtil import com.wire.kalium.network.BackendMetaDataUtilImpl -import com.wire.kalium.network.UnboundNetworkClient +import com.wire.kalium.network.UnauthenticatedNetworkClient import com.wire.kalium.network.tools.ServerConfigDTO import com.wire.kalium.network.utils.NetworkResponse import com.wire.kalium.network.utils.mapSuccess @@ -37,11 +37,12 @@ interface VersionApi { class VersionApiImpl internal constructor( private val httpClient: HttpClient, - private val util: BackendMetaDataUtil = BackendMetaDataUtilImpl, - private val developmentApiEnabled: Boolean + private val developmentApiEnabled: Boolean, + private val util: BackendMetaDataUtil = BackendMetaDataUtilImpl ) : VersionApi { - internal constructor(unboundNetworkClient: UnboundNetworkClient, developmentApiEnabled: Boolean) : this( - unboundNetworkClient.httpClient, + + internal constructor(unauthenticatedNetworkClient: UnauthenticatedNetworkClient, developmentApiEnabled: Boolean) : this( + unauthenticatedNetworkClient.httpClient, developmentApiEnabled = developmentApiEnabled ) diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v0/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV0.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v0/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV0.kt index 02d01312209..2c60aa5eeb8 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v0/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV0.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v0/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV0.kt @@ -27,6 +27,10 @@ import com.wire.kalium.network.api.base.unauthenticated.VerificationCodeApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApiImpl import com.wire.kalium.network.api.base.unauthenticated.register.RegisterApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApiImpl +import com.wire.kalium.network.api.base.unbound.versioning.VersionApi +import com.wire.kalium.network.api.base.unbound.versioning.VersionApiImpl import com.wire.kalium.network.api.v0.unauthenticated.DomainLookupApiV0 import com.wire.kalium.network.api.v0.unauthenticated.LoginApiV0 import com.wire.kalium.network.api.v0.unauthenticated.RegisterApiV0 @@ -40,7 +44,9 @@ import com.wire.kalium.network.session.CertificatePinning import com.wire.kalium.network.tools.ServerConfigDTO import io.ktor.client.engine.HttpClientEngine +@Suppress("LongParameterList") class UnauthenticatedNetworkContainerV0 internal constructor( + private val developmentApiEnabled: Boolean, networkStateObserver: NetworkStateObserver, backendLinks: ServerConfigDTO, proxyCredentials: ProxyCredentialsDTO?, @@ -62,5 +68,8 @@ class UnauthenticatedNetworkContainerV0 internal constructor( override val domainLookupApi: DomainLookupApi get() = DomainLookupApiV0(unauthenticatedNetworkClient) override val registerApi: RegisterApi get() = RegisterApiV0(unauthenticatedNetworkClient) override val sso: SSOLoginApi get() = SSOLoginApiV0(unauthenticatedNetworkClient) + override val remoteVersion: VersionApi get() = VersionApiImpl(unauthenticatedNetworkClient, developmentApiEnabled) + override val serverConfigApi: ServerConfigApi + get() = ServerConfigApiImpl(unauthenticatedNetworkClient) override val appVersioningApi: AppVersioningApi get() = AppVersioningApiImpl(unauthenticatedNetworkClient) } diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v2/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV2.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v2/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV2.kt index caa5b347b12..b0fecb9dfac 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v2/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV2.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v2/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV2.kt @@ -27,6 +27,10 @@ import com.wire.kalium.network.api.base.unauthenticated.VerificationCodeApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApiImpl import com.wire.kalium.network.api.base.unauthenticated.register.RegisterApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApiImpl +import com.wire.kalium.network.api.base.unbound.versioning.VersionApi +import com.wire.kalium.network.api.base.unbound.versioning.VersionApiImpl import com.wire.kalium.network.api.v2.unauthenticated.DomainLookupApiV2 import com.wire.kalium.network.api.v2.unauthenticated.LoginApiV2 import com.wire.kalium.network.api.v2.unauthenticated.RegisterApiV2 @@ -40,7 +44,9 @@ import com.wire.kalium.network.session.CertificatePinning import com.wire.kalium.network.tools.ServerConfigDTO import io.ktor.client.engine.HttpClientEngine +@Suppress("LongParameterList") class UnauthenticatedNetworkContainerV2 internal constructor( + private val developmentApiEnabled: Boolean, networkStateObserver: NetworkStateObserver, backendLinks: ServerConfigDTO, proxyCredentials: ProxyCredentialsDTO?, @@ -62,5 +68,8 @@ class UnauthenticatedNetworkContainerV2 internal constructor( override val domainLookupApi: DomainLookupApi get() = DomainLookupApiV2(unauthenticatedNetworkClient) override val registerApi: RegisterApi get() = RegisterApiV2(unauthenticatedNetworkClient) override val sso: SSOLoginApi get() = SSOLoginApiV2(unauthenticatedNetworkClient) + override val remoteVersion: VersionApi get() = VersionApiImpl(unauthenticatedNetworkClient, developmentApiEnabled) + override val serverConfigApi: ServerConfigApi + get() = ServerConfigApiImpl(unauthenticatedNetworkClient) override val appVersioningApi: AppVersioningApi get() = AppVersioningApiImpl(unauthenticatedNetworkClient) } diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v3/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV3.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v3/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV3.kt index 7ab4887bce0..debac177341 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v3/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV3.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v3/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV3.kt @@ -27,6 +27,10 @@ import com.wire.kalium.network.api.base.unauthenticated.VerificationCodeApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApiImpl import com.wire.kalium.network.api.base.unauthenticated.register.RegisterApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApiImpl +import com.wire.kalium.network.api.base.unbound.versioning.VersionApi +import com.wire.kalium.network.api.base.unbound.versioning.VersionApiImpl import com.wire.kalium.network.api.v3.unauthenticated.DomainLookupApiV3 import com.wire.kalium.network.api.v3.unauthenticated.LoginApiV3 import com.wire.kalium.network.api.v3.unauthenticated.RegisterApiV3 @@ -40,7 +44,9 @@ import com.wire.kalium.network.session.CertificatePinning import com.wire.kalium.network.tools.ServerConfigDTO import io.ktor.client.engine.HttpClientEngine +@Suppress("LongParameterList") class UnauthenticatedNetworkContainerV3 internal constructor( + private val developmentApiEnabled: Boolean, networkStateObserver: NetworkStateObserver, backendLinks: ServerConfigDTO, proxyCredentials: ProxyCredentialsDTO?, @@ -62,5 +68,8 @@ class UnauthenticatedNetworkContainerV3 internal constructor( override val domainLookupApi: DomainLookupApi get() = DomainLookupApiV3(unauthenticatedNetworkClient) override val registerApi: RegisterApi get() = RegisterApiV3(unauthenticatedNetworkClient) override val sso: SSOLoginApi get() = SSOLoginApiV3(unauthenticatedNetworkClient) + override val remoteVersion: VersionApi get() = VersionApiImpl(unauthenticatedNetworkClient, developmentApiEnabled) + override val serverConfigApi: ServerConfigApi + get() = ServerConfigApiImpl(unauthenticatedNetworkClient) override val appVersioningApi: AppVersioningApi get() = AppVersioningApiImpl(unauthenticatedNetworkClient) } diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v4/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV4.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v4/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV4.kt index df2c7325a47..f09670112a5 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v4/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV4.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v4/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV4.kt @@ -27,6 +27,10 @@ import com.wire.kalium.network.api.base.unauthenticated.VerificationCodeApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApiImpl import com.wire.kalium.network.api.base.unauthenticated.register.RegisterApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApiImpl +import com.wire.kalium.network.api.base.unbound.versioning.VersionApi +import com.wire.kalium.network.api.base.unbound.versioning.VersionApiImpl import com.wire.kalium.network.api.v4.unauthenticated.DomainLookupApiV4 import com.wire.kalium.network.api.v4.unauthenticated.LoginApiV4 import com.wire.kalium.network.api.v4.unauthenticated.RegisterApiV4 @@ -40,7 +44,9 @@ import com.wire.kalium.network.session.CertificatePinning import com.wire.kalium.network.tools.ServerConfigDTO import io.ktor.client.engine.HttpClientEngine +@Suppress("LongParameterList") class UnauthenticatedNetworkContainerV4 internal constructor( + private val developmentApiEnabled: Boolean, networkStateObserver: NetworkStateObserver, backendLinks: ServerConfigDTO, proxyCredentials: ProxyCredentialsDTO?, @@ -60,6 +66,9 @@ class UnauthenticatedNetworkContainerV4 internal constructor( override val loginApi: LoginApi get() = LoginApiV4(unauthenticatedNetworkClient) override val verificationCodeApi: VerificationCodeApi get() = VerificationCodeApiV4(unauthenticatedNetworkClient) override val domainLookupApi: DomainLookupApi get() = DomainLookupApiV4(unauthenticatedNetworkClient) + override val remoteVersion: VersionApi get() = VersionApiImpl(unauthenticatedNetworkClient, developmentApiEnabled) + override val serverConfigApi: ServerConfigApi + get() = ServerConfigApiImpl(unauthenticatedNetworkClient) override val registerApi: RegisterApi get() = RegisterApiV4(unauthenticatedNetworkClient) override val sso: SSOLoginApi get() = SSOLoginApiV4(unauthenticatedNetworkClient) override val appVersioningApi: AppVersioningApi get() = AppVersioningApiImpl(unauthenticatedNetworkClient) diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v5/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV5.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v5/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV5.kt index b8af2da7412..054971534e3 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/api/v5/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV5.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/api/v5/unauthenticated/networkContainer/UnauthenticatedNetworkContainerV5.kt @@ -27,6 +27,10 @@ import com.wire.kalium.network.api.base.unauthenticated.VerificationCodeApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApiImpl import com.wire.kalium.network.api.base.unauthenticated.register.RegisterApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApiImpl +import com.wire.kalium.network.api.base.unbound.versioning.VersionApi +import com.wire.kalium.network.api.base.unbound.versioning.VersionApiImpl import com.wire.kalium.network.api.v5.unauthenticated.DomainLookupApiV5 import com.wire.kalium.network.api.v5.unauthenticated.LoginApiV5 import com.wire.kalium.network.api.v5.unauthenticated.RegisterApiV5 @@ -40,7 +44,9 @@ import com.wire.kalium.network.session.CertificatePinning import com.wire.kalium.network.tools.ServerConfigDTO import io.ktor.client.engine.HttpClientEngine +@Suppress("LongParameterList") class UnauthenticatedNetworkContainerV5 internal constructor( + private val developmentApiEnabled: Boolean, networkStateObserver: NetworkStateObserver, backendLinks: ServerConfigDTO, proxyCredentials: ProxyCredentialsDTO?, @@ -60,6 +66,9 @@ class UnauthenticatedNetworkContainerV5 internal constructor( override val loginApi: LoginApi get() = LoginApiV5(unauthenticatedNetworkClient) override val verificationCodeApi: VerificationCodeApi get() = VerificationCodeApiV5(unauthenticatedNetworkClient) override val domainLookupApi: DomainLookupApi get() = DomainLookupApiV5(unauthenticatedNetworkClient) + override val remoteVersion: VersionApi get() = VersionApiImpl(unauthenticatedNetworkClient, developmentApiEnabled) + override val serverConfigApi: ServerConfigApi + get() = ServerConfigApiImpl(unauthenticatedNetworkClient) override val registerApi: RegisterApi get() = RegisterApiV5(unauthenticatedNetworkClient) override val sso: SSOLoginApi get() = SSOLoginApiV5(unauthenticatedNetworkClient) override val appVersioningApi: AppVersioningApi get() = AppVersioningApiImpl(unauthenticatedNetworkClient) diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt index 23be6cd2fe8..fac50ca3c9a 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnauthenticatedNetworkContainer.kt @@ -27,6 +27,8 @@ import com.wire.kalium.network.api.base.unauthenticated.SSOLoginApi import com.wire.kalium.network.api.base.unauthenticated.VerificationCodeApi import com.wire.kalium.network.api.base.unauthenticated.appVersioning.AppVersioningApi import com.wire.kalium.network.api.base.unauthenticated.register.RegisterApi +import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi +import com.wire.kalium.network.api.base.unbound.versioning.VersionApi import com.wire.kalium.network.api.v0.unauthenticated.networkContainer.UnauthenticatedNetworkContainerV0 import com.wire.kalium.network.api.v2.unauthenticated.networkContainer.UnauthenticatedNetworkContainerV2 import com.wire.kalium.network.api.v3.unauthenticated.networkContainer.UnauthenticatedNetworkContainerV3 @@ -44,6 +46,8 @@ interface UnauthenticatedNetworkContainer { val appVersioningApi: AppVersioningApi val verificationCodeApi: VerificationCodeApi val domainLookupApi: DomainLookupApi + val remoteVersion: VersionApi + val serverConfigApi: ServerConfigApi companion object { fun create( @@ -51,6 +55,7 @@ interface UnauthenticatedNetworkContainer { serverConfigDTO: ServerConfigDTO, proxyCredentials: ProxyCredentialsDTO?, userAgent: String, + developmentApiEnabled: Boolean, certificatePinning: CertificatePinning, mockEngine: HttpClientEngine? ): UnauthenticatedNetworkContainer { @@ -59,6 +64,7 @@ interface UnauthenticatedNetworkContainer { return when (serverConfigDTO.metaData.commonApiVersion.version) { 0 -> UnauthenticatedNetworkContainerV0( + developmentApiEnabled, networkStateObserver, serverConfigDTO, proxyCredentials = proxyCredentials, @@ -67,6 +73,7 @@ interface UnauthenticatedNetworkContainer { ) 1 -> UnauthenticatedNetworkContainerV0( + developmentApiEnabled, networkStateObserver, serverConfigDTO, proxyCredentials = proxyCredentials, @@ -75,6 +82,7 @@ interface UnauthenticatedNetworkContainer { ) 2 -> UnauthenticatedNetworkContainerV2( + developmentApiEnabled, networkStateObserver, serverConfigDTO, proxyCredentials = proxyCredentials, @@ -83,6 +91,7 @@ interface UnauthenticatedNetworkContainer { ) 3 -> UnauthenticatedNetworkContainerV3( + developmentApiEnabled, networkStateObserver, serverConfigDTO, proxyCredentials = proxyCredentials, @@ -91,6 +100,7 @@ interface UnauthenticatedNetworkContainer { ) 4 -> UnauthenticatedNetworkContainerV4( + developmentApiEnabled, networkStateObserver, serverConfigDTO, proxyCredentials = proxyCredentials, @@ -99,6 +109,7 @@ interface UnauthenticatedNetworkContainer { ) 5 -> UnauthenticatedNetworkContainerV5( + developmentApiEnabled, networkStateObserver, serverConfigDTO, proxyCredentials = proxyCredentials, diff --git a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnboundNetworkContainer.kt b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnboundNetworkContainer.kt index 200ac759b21..7a77a2e4ec5 100644 --- a/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnboundNetworkContainer.kt +++ b/network/src/commonMain/kotlin/com/wire/kalium/network/networkContainer/UnboundNetworkContainer.kt @@ -24,15 +24,12 @@ import com.wire.kalium.network.api.base.unbound.acme.ACMEApi import com.wire.kalium.network.api.base.unbound.acme.ACMEApiImpl import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApi import com.wire.kalium.network.api.base.unbound.configuration.ServerConfigApiImpl -import com.wire.kalium.network.api.base.unbound.versioning.VersionApi -import com.wire.kalium.network.api.base.unbound.versioning.VersionApiImpl import com.wire.kalium.network.defaultHttpEngine import com.wire.kalium.network.session.CertificatePinning import io.ktor.client.engine.HttpClientEngine interface UnboundNetworkContainer { val serverConfigApi: ServerConfigApi - val remoteVersion: VersionApi val acmeApi: ACMEApi } @@ -57,21 +54,19 @@ internal class UnboundNetworkClientProviderImpl( class UnboundNetworkContainerCommon( networkStateObserver: NetworkStateObserver, - private val developmentApiEnabled: Boolean, userAgent: String, - private val ignoreSSLCertificates: Boolean, certificatePinning: CertificatePinning, mockEngine: HttpClientEngine? ) : UnboundNetworkContainer, UnboundNetworkClientProvider by UnboundNetworkClientProviderImpl( - networkStateObserver = networkStateObserver, - userAgent = userAgent, + networkStateObserver, + userAgent, engine = mockEngine ?: defaultHttpEngine( - ignoreSSLCertificates = ignoreSSLCertificates, - certificatePinning = certificatePinning + certificatePinning = certificatePinning, + proxyCredentials = null, + serverConfigDTOApiProxy = null ) ) { override val serverConfigApi: ServerConfigApi get() = ServerConfigApiImpl(unboundNetworkClient) - override val remoteVersion: VersionApi get() = VersionApiImpl(unboundNetworkClient, developmentApiEnabled) override val acmeApi: ACMEApi get() = ACMEApiImpl(unboundNetworkClient) } diff --git a/network/src/commonTest/kotlin/com/wire/kalium/api/ApiTest.kt b/network/src/commonTest/kotlin/com/wire/kalium/api/ApiTest.kt index 32678b0e534..ddd1a974c71 100644 --- a/network/src/commonTest/kotlin/com/wire/kalium/api/ApiTest.kt +++ b/network/src/commonTest/kotlin/com/wire/kalium/api/ApiTest.kt @@ -32,12 +32,18 @@ import com.wire.kalium.network.networkContainer.KaliumUserAgentProvider import com.wire.kalium.network.serialization.JoseJson import com.wire.kalium.network.serialization.XProtoBuf import com.wire.kalium.network.tools.KtxSerializer -import io.ktor.client.engine.mock.* +import io.ktor.client.engine.mock.MockEngine +import io.ktor.client.engine.mock.respond import io.ktor.client.plugins.auth.providers.BearerAuthProvider import io.ktor.client.plugins.auth.providers.BearerTokens import io.ktor.client.plugins.auth.providers.RefreshTokensParams import io.ktor.client.request.HttpRequestData -import io.ktor.http.* +import io.ktor.http.ContentType +import io.ktor.http.HeadersImpl +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpMethod +import io.ktor.http.HttpStatusCode +import io.ktor.http.URLProtocol import io.ktor.http.content.TextContent import io.ktor.utils.io.ByteReadChannel import kotlinx.serialization.json.JsonElement @@ -170,17 +176,24 @@ internal abstract class ApiTest { statusCode: HttpStatusCode, assertion: (HttpRequestData.() -> Unit) = {}, headers: Map? = null, - + developmentApiEnabled: Boolean = false, networkStateObserver: NetworkStateObserver = DEFAULT_TEST_NETWORK_STATE_OBSERVER, ): UnauthenticatedNetworkClient = - mockUnauthenticatedNetworkClient(ByteReadChannel(responseBody), statusCode, assertion, headers, networkStateObserver) + mockUnauthenticatedNetworkClient( + ByteReadChannel(responseBody), + statusCode, + assertion, + headers, + developmentApiEnabled, + networkStateObserver + ) private fun mockUnauthenticatedNetworkClient( responseBody: ByteReadChannel, statusCode: HttpStatusCode, assertion: (HttpRequestData.() -> Unit) = {}, headers: Map?, - + developmentApiEnabled: Boolean = false, networkStateObserver: NetworkStateObserver = DEFAULT_TEST_NETWORK_STATE_OBSERVER, ): UnauthenticatedNetworkClient { @@ -192,7 +205,8 @@ internal abstract class ApiTest { proxyCredentials = null, networkStateObserver = networkStateObserver, certificatePinning = emptyMap(), - mockEngine = null + mockEngine = null, + developmentApiEnabled = developmentApiEnabled ).unauthenticatedNetworkClient } @@ -206,7 +220,7 @@ internal abstract class ApiTest { fun mockUnauthenticatedNetworkClient( expectedRequests: List, - + developmentApiEnabled: Boolean = false, networkStateObserver: NetworkStateObserver = DEFAULT_TEST_NETWORK_STATE_OBSERVER, ): UnauthenticatedNetworkClient { val mockEngine = MockEngine { currentRequest -> @@ -231,6 +245,7 @@ internal abstract class ApiTest { engine = mockEngine, proxyCredentials = null, networkStateObserver = networkStateObserver, + developmentApiEnabled = developmentApiEnabled, certificatePinning = emptyMap(), mockEngine = null ).unauthenticatedNetworkClient diff --git a/network/src/commonTest/kotlin/com/wire/kalium/api/common/VersionApiTest.kt b/network/src/commonTest/kotlin/com/wire/kalium/api/common/VersionApiTest.kt index e638109f541..251ebf48833 100644 --- a/network/src/commonTest/kotlin/com/wire/kalium/api/common/VersionApiTest.kt +++ b/network/src/commonTest/kotlin/com/wire/kalium/api/common/VersionApiTest.kt @@ -39,7 +39,7 @@ internal class VersionApiTest : ApiTest() { @Test fun givenSuccessResponse_whenFetchingSupportedRemoteVersion_thenRequestIsConfigureCorrectly() = runTest { val expected = ServerConfigDTO.MetaData(true, ApiVersionDTO.Valid(1), "wire.com") - val httpClient = mockUnboundNetworkClient( + val httpClient = mockUnauthenticatedNetworkClient( responseBody = VersionInfoDTOJson.valid.rawJson, statusCode = HttpStatusCode.OK, assertion = { @@ -60,7 +60,7 @@ internal class VersionApiTest : ApiTest() { @Test fun givenDevelopmentApiEnabled_whenFetchingSupportedRemoteVersion_thenResultIsApiVersion2() = runTest { val expected = ServerConfigDTO.MetaData(true, ApiVersionDTO.Valid(2), "wire.com") - val httpClient = mockUnboundNetworkClient( + val httpClient = mockUnauthenticatedNetworkClient( responseBody = VersionInfoDTOJson.valid.rawJson, statusCode = HttpStatusCode.OK, assertion = { @@ -81,7 +81,7 @@ internal class VersionApiTest : ApiTest() { @Test fun given404Response_whenFetchingSupportedRemoteVersion_thenResultIsApiVersion0AndFederationFalse() = runTest { val expected = ServerConfigDTO.MetaData(false, ApiVersionDTO.Valid(0), null) - val httpClient = mockUnboundNetworkClient( + val httpClient = mockUnauthenticatedNetworkClient( responseBody = "", statusCode = HttpStatusCode.NotFound ) diff --git a/persistence/src/commonMain/db_global/com/wire/kalium/persistence/Accounts.sq b/persistence/src/commonMain/db_global/com/wire/kalium/persistence/Accounts.sq index f503bf4e10f..3130400058e 100644 --- a/persistence/src/commonMain/db_global/com/wire/kalium/persistence/Accounts.sq +++ b/persistence/src/commonMain/db_global/com/wire/kalium/persistence/Accounts.sq @@ -68,3 +68,25 @@ UPDATE Accounts SET managed_by = :managedBy WHERE id = :userId; managedBy: SELECT managed_by FROM Accounts WHERE id = :userId; + +allValidAccountsWithServerConfig: +SELECT Accounts.id AS userId, + ServerConfiguration.id AS serverConfigId, + ServerConfiguration.apiBaseUrl, + ServerConfiguration.accountBaseUrl, + ServerConfiguration.webSocketBaseUrl, + ServerConfiguration.blackListUrl, + ServerConfiguration.teamsUrl, + ServerConfiguration.websiteUrl, + ServerConfiguration.isOnPremises, + ServerConfiguration.domain, + ServerConfiguration.commonApiVersion, + ServerConfiguration.federation, + ServerConfiguration.apiProxyHost, + ServerConfiguration.apiProxyPort, + ServerConfiguration.apiProxyNeedsAuthentication, + ServerConfiguration.title +FROM Accounts +INNER JOIN ServerConfiguration + ON Accounts.server_config_id = ServerConfiguration.id +WHERE Accounts.logout_reason IS NULL; diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/AccountsDAO.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/AccountsDAO.kt index 70c80ca2654..c6a5151aff9 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/AccountsDAO.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/AccountsDAO.kt @@ -25,6 +25,7 @@ import com.wire.kalium.persistence.dao.ManagedByEntity import com.wire.kalium.persistence.dao.QualifiedIDEntity import com.wire.kalium.persistence.dao.UserIDEntity import com.wire.kalium.persistence.model.LogoutReason +import com.wire.kalium.persistence.model.ServerConfigEntity import com.wire.kalium.persistence.model.SsoIdEntity import com.wire.kalium.persistence.util.mapToList import com.wire.kalium.persistence.util.mapToOneOrNull @@ -95,6 +96,55 @@ internal object AccountMapper { } else { SsoIdEntity(scim_external_id, subject, tenant) } + + fun fromUserIDWithServerConfig( + userId: QualifiedIDEntity, + serverConfigId: String, + apiBaseUrl: String, + accountBaseUrl: String, + webSocketBaseUrl: String, + blackListUrl: String, + teamsUrl: String, + websiteUrl: String, + isOnPremises: Boolean, + domain: String?, + commonApiVersion: Int, + federation: Boolean, + apiProxyHost: String?, + apiProxyPort: Int?, + apiProxyNeedsAuthentication: Boolean?, + title: String + ): Pair { + val apiProxy: ServerConfigEntity.ApiProxy? = + if (apiProxyHost != null && apiProxyPort != null && apiProxyNeedsAuthentication != null) { + ServerConfigEntity.ApiProxy(apiProxyNeedsAuthentication, apiProxyHost, apiProxyPort) + } else { + null + } + + val serverConfig = ServerConfigEntity( + id = serverConfigId, + links = ServerConfigEntity.Links( + api = apiBaseUrl, + accounts = accountBaseUrl, + webSocket = webSocketBaseUrl, + blackList = blackListUrl, + teams = teamsUrl, + website = websiteUrl, + isOnPremises = isOnPremises, + apiProxy = apiProxy, + title = title + ), + metaData = ServerConfigEntity.MetaData( + domain = domain, + apiVersion = commonApiVersion, + federation = federation, + ) + ) + + return userId to serverConfig + } + } @Suppress("TooManyFunctions") @@ -126,6 +176,7 @@ interface AccountsDAO { fun fullAccountInfo(userIDEntity: UserIDEntity): FullAccountEntity? suspend fun getAllValidAccountPersistentWebSocketStatus(): Flow> suspend fun getAccountManagedBy(userIDEntity: UserIDEntity): ManagedByEntity? + suspend fun validAccountWithServerConfigId(): Map } @Suppress("TooManyFunctions") @@ -252,6 +303,10 @@ internal class AccountsDAOImpl internal constructor( queries.managedBy(userIDEntity).executeAsOneOrNull()?.managed_by } + override suspend fun validAccountWithServerConfigId(): Map = withContext(queriesContext) { + queries.allValidAccountsWithServerConfig(mapper = mapper::fromUserIDWithServerConfig).executeAsList().toMap() + } + override suspend fun accountInfo(userIDEntity: UserIDEntity): AccountInfoEntity? = withContext(queriesContext) { queries.accountInfo(userIDEntity, mapper = mapper::fromAccount).executeAsOneOrNull() } diff --git a/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt b/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt index 3d831e2fd4c..5f74ca7465a 100644 --- a/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt +++ b/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt @@ -118,7 +118,7 @@ class PocIntegrationTest { isOnPremises = true, apiProxy = null ) - ).invoke() + ).invoke(null) if (result !is AutoVersionAuthScopeUseCase.Result.Success) { error("Failed getting AuthScope: $result") } diff --git a/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/InstanceService.kt b/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/InstanceService.kt index 44c6e3c5c43..ffa94a2cdc3 100644 --- a/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/InstanceService.kt +++ b/testservice/src/main/kotlin/com/wire/kalium/testservice/managed/InstanceService.kt @@ -24,6 +24,7 @@ import com.wire.kalium.logger.KaliumLogLevel import com.wire.kalium.logic.CoreLogger import com.wire.kalium.logic.CoreLogic import com.wire.kalium.logic.configuration.server.ServerConfig +import com.wire.kalium.logic.data.auth.login.ProxyCredentials import com.wire.kalium.logic.data.client.ClientType import com.wire.kalium.logic.data.client.DeleteClientParam import com.wire.kalium.logic.data.conversation.ClientId @@ -168,7 +169,7 @@ class InstanceService( } log.info("Instance $instanceId: Login with ${instanceRequest.email} on ${instanceRequest.backend}") - val loginResult = provideVersionedAuthenticationScope(coreLogic, serverConfig) + val loginResult = provideVersionedAuthenticationScope(coreLogic, serverConfig, null) .login( instanceRequest.email, instanceRequest.password, true, secondFactorVerificationCode = instanceRequest.verificationCode @@ -285,15 +286,21 @@ class InstanceService( // close the stream files.close() } catch (e: IOException) { - log.warn("Instance ${instance.instanceId}: Could not delete directory ${instance.instancePath}: " - + e.message) + log.warn( + "Instance ${instance.instanceId}: Could not delete directory ${instance.instancePath}: " + + e.message + ) } } }, deleteLocalFilesTimeoutInMinutes.toMinutes(), TimeUnit.MINUTES) } - private suspend fun provideVersionedAuthenticationScope(coreLogic: CoreLogic, serverLinks: ServerConfig.Links): AuthenticationScope = - when (val result = coreLogic.versionedAuthenticationScope(serverLinks).invoke()) { + private suspend fun provideVersionedAuthenticationScope( + coreLogic: CoreLogic, + serverLinks: ServerConfig.Links, + proxyCredentials: ProxyCredentials? + ): AuthenticationScope = + when (val result = coreLogic.versionedAuthenticationScope(serverLinks).invoke(proxyCredentials)) { is AutoVersionAuthScopeUseCase.Result.Failure.Generic -> throw WebApplicationException("failed to create authentication scope: ${result.genericFailure}")