From ee53377070833feafa1eaa0e383f4839fedb93c8 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Fri, 12 Apr 2024 12:55:04 +0400 Subject: [PATCH] core: fix forwarded item deletion (#4018) --- src/Simplex/Chat.hs | 8 ++++---- src/Simplex/Chat/Messages.hs | 11 +++++++---- src/Simplex/Chat/Store/Messages.hs | 4 ++-- tests/ChatTests/Forward.hs | 22 ++++++++++++++++++++++ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index ffb04dc9c3..441b7994b6 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -787,8 +787,8 @@ processChatCommand' vr = \case CTContactConnection -> pure $ chatCmdError (Just user) "not supported" APIDeleteChatItem (ChatRef cType chatId) itemId mode -> withUser $ \user -> case cType of CTDirect -> withContactLock "deleteChatItem" chatId $ do - (ct, CChatItem msgDir ci@ChatItem {meta = CIMeta {itemSharedMsgId, editable}}) <- withStore $ \db -> (,) <$> getContact db vr user chatId <*> getDirectChatItem db user chatId itemId - case (mode, msgDir, itemSharedMsgId, editable) of + (ct, CChatItem msgDir ci@ChatItem {meta = CIMeta {itemSharedMsgId, deletable}}) <- withStore $ \db -> (,) <$> getContact db vr user chatId <*> getDirectChatItem db user chatId itemId + case (mode, msgDir, itemSharedMsgId, deletable) of (CIDMInternal, _, _, _) -> deleteDirectCI user ct ci True False (CIDMBroadcast, SMDSnd, Just itemSharedMId, True) -> do assertDirectAllowed user MDSnd ct XMsgDel_ @@ -799,8 +799,8 @@ processChatCommand' vr = \case (CIDMBroadcast, _, _, _) -> throwChatError CEInvalidChatItemDelete CTGroup -> withGroupLock "deleteChatItem" chatId $ do Group gInfo ms <- withStore $ \db -> getGroup db vr user chatId - CChatItem msgDir ci@ChatItem {meta = CIMeta {itemSharedMsgId, editable}} <- withStore $ \db -> getGroupChatItem db user chatId itemId - case (mode, msgDir, itemSharedMsgId, editable) of + CChatItem msgDir ci@ChatItem {meta = CIMeta {itemSharedMsgId, deletable}} <- withStore $ \db -> getGroupChatItem db user chatId itemId + case (mode, msgDir, itemSharedMsgId, deletable) of (CIDMInternal, _, _, _) -> deleteGroupCI user gInfo ci True False Nothing =<< liftIO getCurrentTime (CIDMBroadcast, SMDSnd, Just itemSharedMId, True) -> do assertUserGroupRole gInfo GRObserver -- can still delete messages sent earlier diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 2aa781d45e..a6d5761b5f 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -344,6 +344,7 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta itemEdited :: Bool, itemTimed :: Maybe CITimed, itemLive :: Maybe Bool, + deletable :: Bool, editable :: Bool, forwardedByMember :: Maybe GroupMemberId, createdAt :: UTCTime, @@ -353,13 +354,14 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta mkCIMeta :: forall c d. ChatTypeI c => ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe SharedMsgId -> Maybe CIForwardedFrom -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> UTCTime -> CIMeta c d mkCIMeta itemId itemContent itemText itemStatus itemSharedMsgId itemForwarded itemDeleted itemEdited itemTimed itemLive currentTs itemTs forwardedByMember createdAt updatedAt = - let editable = case itemContent of + let deletable = case itemContent of CISndMsgContent _ -> case chatTypeI @c of - SCTLocal -> isNothing itemDeleted && isNothing itemForwarded - _ -> diffUTCTime currentTs itemTs < nominalDay && isNothing itemDeleted && isNothing itemForwarded + SCTLocal -> isNothing itemDeleted + _ -> diffUTCTime currentTs itemTs < nominalDay && isNothing itemDeleted _ -> False - in CIMeta {itemId, itemTs, itemText, itemStatus, itemSharedMsgId, itemForwarded, itemDeleted, itemEdited, itemTimed, itemLive, editable, forwardedByMember, createdAt, updatedAt} + editable = deletable && isNothing itemForwarded + in CIMeta {itemId, itemTs, itemText, itemStatus, itemSharedMsgId, itemForwarded, itemDeleted, itemEdited, itemTimed, itemLive, deletable, editable, forwardedByMember, createdAt, updatedAt} dummyMeta :: ChatItemId -> UTCTime -> Text -> CIMeta c 'MDSnd dummyMeta itemId ts itemText = @@ -374,6 +376,7 @@ dummyMeta itemId ts itemText = itemEdited = False, itemTimed = Nothing, itemLive = Nothing, + deletable = False, editable = False, forwardedByMember = Nothing, createdAt = ts, diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index 11068ff5cb..2e4ee6e48f 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -1874,7 +1874,7 @@ updateGroupChatItemModerated db User {userId} GroupInfo {groupId} ci m@GroupMemb WHERE user_id = ? AND group_id = ? AND chat_item_id = ? |] (deletedTs, groupMemberId, toContent, toText, currentTs, userId, groupId, itemId) - pure $ ci {content = toContent, meta = (meta ci) {itemText = toText, itemDeleted = Just (CIModerated (Just deletedTs) m), editable = False}, formattedText = Nothing} + pure $ ci {content = toContent, meta = (meta ci) {itemText = toText, itemDeleted = Just (CIModerated (Just deletedTs) m), editable = False, deletable = False}, formattedText = Nothing} updateGroupCIBlockedByAdmin :: DB.Connection -> User -> GroupInfo -> ChatItem 'CTGroup d -> UTCTime -> IO (ChatItem 'CTGroup d) updateGroupCIBlockedByAdmin db User {userId} GroupInfo {groupId} ci deletedTs = do @@ -1891,7 +1891,7 @@ updateGroupCIBlockedByAdmin db User {userId} GroupInfo {groupId} ci deletedTs = WHERE user_id = ? AND group_id = ? AND chat_item_id = ? |] (DBCIBlockedByAdmin, deletedTs, currentTs, userId, groupId, itemId) - pure $ ci {meta = (meta ci) {itemDeleted = Just (CIBlockedByAdmin $ Just deletedTs), editable = False}, formattedText = Nothing} + pure $ ci {meta = (meta ci) {itemDeleted = Just (CIBlockedByAdmin $ Just deletedTs), editable = False, deletable = False}, formattedText = Nothing} pattern DBCINotDeleted :: Int pattern DBCINotDeleted = 0 diff --git a/tests/ChatTests/Forward.hs b/tests/ChatTests/Forward.hs index 6aea8447b9..4bd75d0e5b 100644 --- a/tests/ChatTests/Forward.hs +++ b/tests/ChatTests/Forward.hs @@ -25,6 +25,7 @@ chatForwardTests = do it "preserve original forward info" testForwardPreserveInfo it "quoted message is not included" testForwardQuotedMsg it "editing is prohibited" testForwardEditProhibited + it "delete for other" testForwardDeleteForOther describe "forward files" $ do it "from contact to contact" testForwardFileNoFilesFolder it "with relative paths: from contact to contact" testForwardFileContactToContact @@ -307,6 +308,27 @@ testForwardEditProhibited = alice ##> ("/_update item @3 " <> msgId <> " text hey edited") alice <## "cannot update this item" +testForwardDeleteForOther :: HasCallStack => FilePath -> IO () +testForwardDeleteForOther = + testChat3 aliceProfile bobProfile cathProfile $ + \alice bob cath -> do + connectUsers alice bob + connectUsers alice cath + + bob #> "@alice hey" + alice <# "bob> hey" + + alice `send` "@cath <- @bob hey" + alice <# "@cath <- @bob" + alice <## " hey" + cath <# "alice> -> forwarded" + cath <## " hey" + + msgId <- lastItemId alice + alice ##> ("/_delete item @3 " <> msgId <> " broadcast") + alice <## "message marked deleted" + cath <# "alice> [marked deleted] hey" + testForwardFileNoFilesFolder :: HasCallStack => FilePath -> IO () testForwardFileNoFilesFolder = testChat3 aliceProfile bobProfile cathProfile $