From 9052e46d101b39ecd651084de7d700e741958950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Kalici=C5=84ski?= Date: Fri, 25 Oct 2024 14:35:15 +0200 Subject: [PATCH] Match behavior from TS more closely regarding hard delete status. Previously we diverged by returning the last known version of the data, this reverts it to returning `null` when hard deleting users and channels. --- .../kotlin/com/pubnub/chat/Channel.kt | 4 +- .../commonMain/kotlin/com/pubnub/chat/Chat.kt | 9 ++-- .../kotlin/com/pubnub/chat/Message.kt | 4 +- .../commonMain/kotlin/com/pubnub/chat/User.kt | 4 +- .../com/pubnub/chat/internal/ChatImpl.kt | 51 +++++++++---------- .../com/pubnub/chat/internal/ChatInternal.kt | 2 +- .../com/pubnub/chat/internal/UserImpl.kt | 2 +- .../chat/internal/channel/BaseChannel.kt | 2 +- .../internal/channel/ThreadChannelImpl.kt | 2 +- .../chat/internal/message/BaseMessage.kt | 3 +- .../pubnub/integration/AccessManagerTest.kt | 7 +++ .../integration/BaseChatIntegrationTest.kt | 6 ++- .../kotlin/com/pubnub/kmp/ChannelTest.kt | 2 +- .../kotlin/com/pubnub/kmp/ChatTest.kt | 2 +- .../kotlin/com/pubnub/kmp/UserTest.kt | 4 +- .../kotlin/com/pubnub/kmp/utils/FakeChat.kt | 6 +-- 16 files changed, 58 insertions(+), 52 deletions(-) diff --git a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Channel.kt b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Channel.kt index 2a3884f1..fe5389ce 100644 --- a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Channel.kt +++ b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Channel.kt @@ -105,10 +105,10 @@ interface Channel { * @param soft Decide if you want to permanently remove channel metadata. The channel metadata gets permanently * deleted from the App Context storage by default. If you set this parameter to true, the Channel object * gets the deleted status, and you can still restore/get its data. - * @return For hard delete, the method returns [PNFuture] with the last version of the [Channel] object before it was permanently deleted. + * @return For hard delete, the method returns [PNFuture] without a value (`null`). * For soft delete, [PNFuture] containing an updated [Channel] instance with the status field set to "deleted". */ - fun delete(soft: Boolean = false): PNFuture + fun delete(soft: Boolean = false): PNFuture /** * Forwards message to existing [Channel] diff --git a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Chat.kt b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Chat.kt index 128172cb..edd81108 100644 --- a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Chat.kt +++ b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Chat.kt @@ -148,9 +148,10 @@ interface Chat { * from the App Context storage by default. If you set this parameter to true, the User object gets the deleted * status, and you can still restore/get their metadata. * - * @return [PNFuture] containing [User] object. + * @return For hard delete, the method returns [PNFuture] without a value (`null`). + * For soft delete, [PNFuture] containing an updated [User] instance with the status field set to "deleted". */ - fun deleteUser(id: String, soft: Boolean = false): PNFuture + fun deleteUser(id: String, soft: Boolean = false): PNFuture /** * Retrieves list of [Channel.id] where a given user is present. @@ -228,10 +229,10 @@ interface Chat { * deleted from the App Context storage by default. If you set this parameter to true, the Channel object * gets the deleted status, and you can still restore/get its data. * - * @return For hard delete, the method returns [PNFuture] with the last version of the [Channel] object before it was permanently deleted. + * @return For hard delete, the method returns [PNFuture] without a value (`null`). * For soft delete, [PNFuture] containing an updated [Channel] instance with the status field set to "deleted". */ - fun deleteChannel(id: String, soft: Boolean = false): PNFuture + fun deleteChannel(id: String, soft: Boolean = false): PNFuture /** * Returns a list of [User.id] present on the given [Channel]. diff --git a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Message.kt b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Message.kt index fc3ff3d8..121d63c4 100644 --- a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Message.kt +++ b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/Message.kt @@ -130,7 +130,7 @@ interface Message { * * @param soft Decide if you want to permanently remove message data. By default, the message data gets permanently deleted from Message Persistence. If you set this parameter to true, the Message object gets the deleted status and you can still restore/get its data. * @param preserveFiles Define if you want to keep the files attached to the message or remove them. - * @return For hard delete, the method returns the last version of the Message object before it was permanently deleted. For soft delete, an updated message instance with an added deleted action type. + * @return For hard delete, the method returns `PNFuture` without a value (`null`). For soft delete, a `PNFuture` with an updated message instance with an added deleted action type. */ fun delete(soft: Boolean = false, preserveFiles: Boolean = false): PNFuture @@ -178,7 +178,7 @@ interface Message { * * @return A pair of values containing an object with details about the result of the remove message action (indicating whether the message was successfully removed and potentially including additional metadata or information about the removal) and the updated channel object after the removal of the thread. */ - fun removeThread(): PNFuture> // todo add test + fun removeThread(): PNFuture> // todo add test /** * Add or remove a reaction to a message. diff --git a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/User.kt b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/User.kt index 03fef555..23595824 100644 --- a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/User.kt +++ b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/User.kt @@ -102,10 +102,10 @@ interface User { * Deletes the user. If soft deletion is enabled, the user's data is retained but marked as inactive. * * @param soft If true, the user is soft deleted, retaining their data but making them inactive. - * @return For hard delete, the method returns [PNFuture] with the last version of the [User] object before it was permanently deleted. + * @return For hard delete, the method returns [PNFuture] without a value (`null`). * For soft delete, [PNFuture] containing an updated [User] instance with the status field set to "deleted". */ - fun delete(soft: Boolean = false): PNFuture + fun delete(soft: Boolean = false): PNFuture /** * Retrieves a list of channels where the user is currently present. diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt index 29faa74f..f87d3606 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt @@ -50,13 +50,13 @@ import com.pubnub.chat.internal.error.PubNubErrorMessage.CANNOT_FORWARD_MESSAGE_ import com.pubnub.chat.internal.error.PubNubErrorMessage.CAN_NOT_FIND_CHANNEL_WITH_ID import com.pubnub.chat.internal.error.PubNubErrorMessage.CHANNEL_ID_ALREADY_EXIST import com.pubnub.chat.internal.error.PubNubErrorMessage.CHANNEL_ID_IS_REQUIRED +import com.pubnub.chat.internal.error.PubNubErrorMessage.CHANNEL_NOT_EXIST import com.pubnub.chat.internal.error.PubNubErrorMessage.CHANNEL_NOT_FOUND import com.pubnub.chat.internal.error.PubNubErrorMessage.COUNT_SHOULD_NOT_EXCEED_100 import com.pubnub.chat.internal.error.PubNubErrorMessage.DEVICE_TOKEN_HAS_TO_BE_DEFINED_IN_CHAT_PUSHNOTIFICATIONS_CONFIG import com.pubnub.chat.internal.error.PubNubErrorMessage.FAILED_TO_CREATE_UPDATE_CHANNEL_DATA import com.pubnub.chat.internal.error.PubNubErrorMessage.FAILED_TO_CREATE_UPDATE_USER_DATA import com.pubnub.chat.internal.error.PubNubErrorMessage.FAILED_TO_FORWARD_MESSAGE -import com.pubnub.chat.internal.error.PubNubErrorMessage.FAILED_TO_RETRIEVE_CHANNEL_DATA import com.pubnub.chat.internal.error.PubNubErrorMessage.FAILED_TO_RETRIEVE_WHO_IS_PRESENT_DATA import com.pubnub.chat.internal.error.PubNubErrorMessage.FAILED_TO_SOFT_DELETE_CHANNEL import com.pubnub.chat.internal.error.PubNubErrorMessage.ID_IS_REQUIRED @@ -229,7 +229,7 @@ class ChatImpl( chat: Chat, message: Message, soft: Boolean - ): PNFuture> { + ): PNFuture> { if (!message.hasThread) { return PubNubException(THERE_IS_NO_THREAD_TO_BE_DELETED).logErrorAndReturnException(log).asFuture() } @@ -321,19 +321,20 @@ class ChatImpl( } } - override fun deleteUser(id: String, soft: Boolean): PNFuture { + override fun deleteUser(id: String, soft: Boolean): PNFuture { if (!isValidId(id)) { return PubNubException(ID_IS_REQUIRED).logErrorAndReturnException(log).asFuture() } - return getUser(id).thenAsync { user: User? -> - user?.let { notNullUser -> - if (soft) { - performSoftUserDelete(notNullUser) - } else { - performUserDelete(notNullUser) + return if (soft) { + getUser(id).thenAsync { user: User? -> + if (user == null) { + log.pnError(USER_NOT_EXIST) } - } ?: log.pnError(USER_NOT_EXIST) + performSoftUserDelete(user) + } + } else { + performUserDelete(id).then { null } } } @@ -454,17 +455,20 @@ class ChatImpl( } } - override fun deleteChannel(id: String, soft: Boolean): PNFuture { + override fun deleteChannel(id: String, soft: Boolean): PNFuture { if (!isValidId(id)) { return log.logErrorAndReturnException(CHANNEL_ID_IS_REQUIRED).asFuture() } - return getChannelData(id).thenAsync { channel: Channel -> - if (soft) { + return if (soft) { + getChannel(id).thenAsync { channel -> + if (channel == null) { + log.pnError(CHANNEL_NOT_EXIST) + } performSoftChannelDelete(channel) - } else { - performChannelDelete(channel) } + } else { + performChannelDelete(id).then { null } } } @@ -1036,15 +1040,6 @@ class ChatImpl( return id.isNotEmpty() } - private fun getChannelData(id: String): PNFuture { - return pubNub.getChannelMetadata(channel = id, includeCustom = false) - .then { pnChannelMetadataResult: PNChannelMetadataResult -> - ChannelImpl.fromDTO(this, pnChannelMetadataResult.data) - }.catch { exception -> - Result.failure(PubNubException(FAILED_TO_RETRIEVE_CHANNEL_DATA, exception)) - } - } - private fun performSoftUserDelete(user: User): PNFuture { val updatedUser = (user as UserImpl).copy(status = DELETED) return pubNub.setUUIDMetadata( @@ -1062,8 +1057,8 @@ class ChatImpl( } } - private fun performUserDelete(user: User): PNFuture = - pubNub.removeUUIDMetadata(uuid = user.id).then { user } + private fun performUserDelete(userId: String): PNFuture = + pubNub.removeUUIDMetadata(uuid = userId).then { } private fun performSoftChannelDelete(channel: Channel): PNFuture { val updatedChannel = (channel as BaseChannel<*, *>).copyWithStatusDeleted() @@ -1082,8 +1077,8 @@ class ChatImpl( } } - private fun performChannelDelete(channel: Channel) = - pubNub.removeChannelMetadata(channel = channel.id).then { channel } + private fun performChannelDelete(channelId: String): PNFuture = + pubNub.removeChannelMetadata(channel = channelId).then { } private fun setChannelMetadata( id: String, diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatInternal.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatInternal.kt index 2e146752..a220315f 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatInternal.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatInternal.kt @@ -25,7 +25,7 @@ interface ChatInternal : Chat { chat: Chat, message: Message, soft: Boolean = false - ): PNFuture> + ): PNFuture> fun restoreThreadChannel(message: Message): PNFuture diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/UserImpl.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/UserImpl.kt index 76ab9ea1..b1fd5fc2 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/UserImpl.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/UserImpl.kt @@ -80,7 +80,7 @@ data class UserImpl( ) } - override fun delete(soft: Boolean): PNFuture { + override fun delete(soft: Boolean): PNFuture { return chat.deleteUser(id, soft) } diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/BaseChannel.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/BaseChannel.kt index 654b9db3..0117427b 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/BaseChannel.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/BaseChannel.kt @@ -137,7 +137,7 @@ abstract class BaseChannel( return chat.updateChannel(id, name, custom, description, status, type) } - override fun delete(soft: Boolean): PNFuture { + override fun delete(soft: Boolean): PNFuture { return chat.deleteChannel(id, soft) } diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/ThreadChannelImpl.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/ThreadChannelImpl.kt index 273cb463..2d2b9906 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/ThreadChannelImpl.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/channel/ThreadChannelImpl.kt @@ -75,7 +75,7 @@ data class ThreadChannelImpl( } } - override fun delete(soft: Boolean): PNFuture { + override fun delete(soft: Boolean): PNFuture { return chat.removeThreadChannel(chat, parentMessage, soft).then { it.second } } diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt index 44f799a1..18048968 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt @@ -9,6 +9,7 @@ import com.pubnub.api.models.consumer.PNPublishResult import com.pubnub.api.models.consumer.history.PNFetchMessageItem import com.pubnub.api.models.consumer.message_actions.PNAddMessageActionResult import com.pubnub.api.models.consumer.message_actions.PNMessageAction +import com.pubnub.api.models.consumer.message_actions.PNRemoveMessageActionResult import com.pubnub.chat.Channel import com.pubnub.chat.Message import com.pubnub.chat.ThreadChannel @@ -201,7 +202,7 @@ abstract class BaseMessage( override fun createThread(): PNFuture = ChatImpl.createThreadChannel(chat, this) - override fun removeThread() = chat.removeThreadChannel(chat, this) + override fun removeThread(): PNFuture> = chat.removeThreadChannel(chat, this) override fun toggleReaction(reaction: String): PNFuture { val existingReaction = reactions[reaction]?.find { diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/AccessManagerTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/AccessManagerTest.kt index f6b5224a..45f15fe0 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/AccessManagerTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/AccessManagerTest.kt @@ -7,6 +7,7 @@ import com.pubnub.chat.Event import com.pubnub.chat.internal.message.MessageImpl import com.pubnub.chat.listenForEvents import com.pubnub.chat.types.EventContent +import com.pubnub.internal.PLATFORM import com.pubnub.test.await import kotlinx.coroutines.test.runTest import kotlin.test.Test @@ -25,6 +26,9 @@ class AccessManagerTest : BaseChatIntegrationTest() { @Test fun pubNubClient_with_PAM_enabled_should_getChannel_when_token_set() = runTest { + if (PLATFORM == "iOS") { + return@runTest + } // getToken from server val channelId = channelPam.id chatPamServer.createChannel(id = channelId).await() @@ -45,6 +49,9 @@ class AccessManagerTest : BaseChatIntegrationTest() { @Test fun setLastReadMessageTimetoken_should_send_Receipt_event_when_has_token() = runTest { + if (PLATFORM == "iOS") { + return@runTest + } var numberOfReceiptEvents = 0 val timetoken = 1000L val channelId = channelPam.id diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt index 8ff011dc..3382c63f 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt @@ -118,8 +118,10 @@ abstract class BaseChatIntegrationTest : BaseIntegrationTest() { fun afterTest() = runTest { try { pubnub.removeUUIDMetadata(someUser.id).await() - pubnubPamServer.removeUUIDMetadata(userPamServer.id).await() - pubnubPamServer.removeUUIDMetadata(userPamClient.id).await() + if (PLATFORM != "iOS") { + pubnubPamServer.removeUUIDMetadata(userPamServer.id).await() + pubnubPamServer.removeUUIDMetadata(userPamClient.id).await() + } pubnub.removeChannelMetadata(channel01.id).await() pubnub.removeChannelMetadata(channel01Chat02.id).await() pubnub.removeChannelMetadata(channel02.id).await() diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChannelTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChannelTest.kt index daccea76..2a4f3c69 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChannelTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChannelTest.kt @@ -134,7 +134,7 @@ class ChannelTest : BaseTest() { val channelFutureMock: PNFuture = mock(MockMode.strict) every { chat.deleteChannel(any(), any()) } returns channelFutureMock - val deleteChannelFuture: PNFuture = objectUnderTest.delete(soft = softDelete) + val deleteChannelFuture: PNFuture = objectUnderTest.delete(soft = softDelete) assertEquals(channelFutureMock, deleteChannelFuture) verify { chat.deleteChannel(id = channelId, soft = softDelete) } diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChatTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChatTest.kt index cf947008..32f68cc9 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChatTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChatTest.kt @@ -306,7 +306,7 @@ class ChatTest : BaseTest() { val softDelete = true // when - objectUnderTest.deleteUser(emptyID, softDelete).async { result: Result -> + objectUnderTest.deleteUser(emptyID, softDelete).async { result: Result -> // then assertTrue(result.isFailure) assertEquals("Id is required", result.exceptionOrNull()?.message) diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/UserTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/UserTest.kt index ea4ea017..febe8c4c 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/UserTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/UserTest.kt @@ -83,7 +83,7 @@ class UserTest { val chat = object : FakeChat(chatConfig, pubNub) { var soft: Boolean? = null - override fun deleteUser(id: String, soft: Boolean): PNFuture { + override fun deleteUser(id: String, soft: Boolean): PNFuture { this.soft = soft return objectUnderTest.asFuture() } @@ -105,7 +105,7 @@ class UserTest { var softDeleted: Boolean? = null var deletedUserId: String? = null - override fun deleteUser(id: String, soft: Boolean): PNFuture { + override fun deleteUser(id: String, soft: Boolean): PNFuture { this.softDeleted = soft this.deletedUserId = id return objectUnderTest.asFuture() diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/utils/FakeChat.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/utils/FakeChat.kt index 065c2a8a..f182d2e3 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/utils/FakeChat.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/utils/FakeChat.kt @@ -61,7 +61,7 @@ abstract class FakeChat(override val config: ChatConfiguration, override val pub chat: Chat, message: Message, soft: Boolean - ): PNFuture> { + ): PNFuture> { TODO("Not yet implemented") } @@ -121,7 +121,7 @@ abstract class FakeChat(override val config: ChatConfiguration, override val pub TODO("Not yet implemented") } - override fun deleteUser(id: String, soft: Boolean): PNFuture { + override fun deleteUser(id: String, soft: Boolean): PNFuture { TODO("Not yet implemented") } @@ -168,7 +168,7 @@ abstract class FakeChat(override val config: ChatConfiguration, override val pub TODO("Not yet implemented") } - override fun deleteChannel(id: String, soft: Boolean): PNFuture { + override fun deleteChannel(id: String, soft: Boolean): PNFuture { TODO("Not yet implemented") }