From 34c4fc72453db7b4f779963b72f2ff3f36d8858f Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Fri, 24 Nov 2023 10:05:50 +0100 Subject: [PATCH] feat: mark user as deleted when server response with 404 (#2259) --- .../kalium/logic/data/user/UserRepository.kt | 19 ++++++++-- .../logic/data/user/UserRepositoryTest.kt | 36 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/user/UserRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/user/UserRepository.kt index a65c28a5365..faee56c88b8 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/user/UserRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/user/UserRepository.kt @@ -49,6 +49,7 @@ import com.wire.kalium.logic.functional.foldToEitherWhileRight import com.wire.kalium.logic.functional.getOrNull import com.wire.kalium.logic.functional.map import com.wire.kalium.logic.functional.mapRight +import com.wire.kalium.logic.functional.onFailure import com.wire.kalium.logic.kaliumLogger import com.wire.kalium.logic.wrapApiRequest import com.wire.kalium.logic.wrapStorageRequest @@ -61,6 +62,8 @@ import com.wire.kalium.network.api.base.authenticated.userDetails.qualifiedIds import com.wire.kalium.network.api.base.model.SelfUserDTO import com.wire.kalium.network.api.base.model.UserProfileDTO import com.wire.kalium.network.api.base.model.isTeamMember +import com.wire.kalium.network.exceptions.KaliumException +import com.wire.kalium.network.exceptions.isNotFound import com.wire.kalium.persistence.dao.ConnectionEntity import com.wire.kalium.persistence.dao.MetadataDAO import com.wire.kalium.persistence.dao.QualifiedIDEntity @@ -226,8 +229,20 @@ internal class UserDataSource internal constructor( return fetchUsersByIds(ids) } + /** + * Fetches user information for all of users id stored in the DB + * and updates the DB with the new information. + * If the user is not found on the server, it will be marked as deleted. + */ override suspend fun fetchUserInfo(userId: UserId) = wrapApiRequest { userDetailsApi.getUserInfo(userId.toApi()) } + .onFailure { + if (it is NetworkFailure.ServerMiscommunication && + it.kaliumException is KaliumException.InvalidRequestError && + it.kaliumException.isNotFound()) { + wrapStorageRequest { userDAO.markUserAsDeleted(userId.toDao()) } + } + } .flatMap { userProfileDTO -> fetchTeamMembersByIds(listOf(userProfileDTO)) .flatMap { persistUsers(listOf(userProfileDTO), it) } @@ -317,8 +332,8 @@ internal class UserDataSource internal constructor( userProfile = userProfileDTO, connectionState = ConnectionEntity.State.ACCEPTED, userTypeEntity = - if (userProfileDTO.service != null) UserTypeEntity.SERVICE - else userTypeEntityMapper.teamRoleCodeToUserType(mapTeamMemberDTO[userProfileDTO.id.value]?.permissions?.own) + if (userProfileDTO.service != null) UserTypeEntity.SERVICE + else userTypeEntityMapper.teamRoleCodeToUserType(mapTeamMemberDTO[userProfileDTO.id.value]?.permissions?.own) ) } val otherUsers = listUserProfileDTO diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/user/UserRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/user/UserRepositoryTest.kt index f987a81745f..b62ae426f3b 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/user/UserRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/user/UserRepositoryTest.kt @@ -48,7 +48,9 @@ import com.wire.kalium.network.api.base.authenticated.userDetails.ListUsersDTO import com.wire.kalium.network.api.base.authenticated.userDetails.QualifiedUserIdListRequest import com.wire.kalium.network.api.base.authenticated.userDetails.UserDetailsApi import com.wire.kalium.network.api.base.authenticated.userDetails.qualifiedIds +import com.wire.kalium.network.api.base.model.ErrorResponse import com.wire.kalium.network.api.base.model.UserProfileDTO +import com.wire.kalium.network.exceptions.KaliumException import com.wire.kalium.network.utils.NetworkResponse import com.wire.kalium.persistence.dao.MetadataDAO import com.wire.kalium.persistence.dao.QualifiedIDEntity @@ -692,6 +694,33 @@ class UserRepositoryTest { .wasNotInvoked() } + @Test + fun givenNotFoundError_whenFetchingAUserInfo_thenMarkAsDeleted() = runTest { + val (arrangement, userRepository) = Arrangement() + .withUserDaoReturning(TestUser.DETAILS_ENTITY.copy(team = TestTeam.TEAM_ID.value)) + .withErrorGetUsersInfo( + NetworkResponse.Error( + KaliumException.InvalidRequestError( + ErrorResponse(404, "Not found", "not-found") + ) + ) + ) + .arrange() + + val result = userRepository.fetchUserInfo(TestUser.USER_ID) + result.shouldFail() + + verify(arrangement.userDetailsApi) + .suspendFunction(arrangement.userDetailsApi::getUserInfo) + .with(any()) + .wasInvoked(exactly = once) + + verify(arrangement.userDAO) + .suspendFunction(arrangement.userDAO::markUserAsDeleted) + .with(any()) + .wasInvoked(exactly = once) + } + private class Arrangement { @Mock val userDAO = configure(mock(classOf())) { stubsUnitByDefault = true } @@ -783,6 +812,13 @@ class UserRepositoryTest { .thenReturn(NetworkResponse.Success(result, mapOf(), 200)) } + fun withErrorGetUsersInfo(error: NetworkResponse.Error) = apply { + given(userDetailsApi) + .suspendFunction(userDetailsApi::getUserInfo) + .whenInvokedWith(any()) + .thenReturn(error) + } + fun withSuccessfulFetchTeamMembersByIds(result: List) = apply { given(teamsApi) .suspendFunction(teamsApi::getTeamMembersByIds)