mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-23 02:12:25 +00:00
core: archive reports when removing member with messages
Reports about a member's messages are authored by the reporter, so deleting the removed member's own chat items never reached them - unlike moderation, which archives them via markMessageReportsDeleted. Reports stayed in the reports list pointing at deleted messages.
This commit is contained in:
1 parent
5847fa7f31
commit
35d541a5a7
5 files changed
+62
-6
No files matched your search
@@ -3171,9 +3171,11 @@ processChatCommand cxt nm = \case
|
||||
then void $ fullyDeleteMemberRecordIO db user gInfo m
|
||||
else void $ deleteOrUpdateMemberRecordIO db user gInfo m
|
||||
pure m {memberStatus = GSMemRemoved}
|
||||
deleteMessages user gInfo@GroupInfo {membership} ms
|
||||
| groupFeatureUserAllowed SGFFullDelete gInfo = deleteGroupMembersCIs user gInfo ms
|
||||
| otherwise = markGroupMembersCIsDeleted user gInfo ms membership
|
||||
deleteMessages user gInfo@GroupInfo {membership} ms = do
|
||||
archiveMembersReports user gInfo ms membership True
|
||||
if groupFeatureUserAllowed SGFFullDelete gInfo
|
||||
then deleteGroupMembersCIs user gInfo ms
|
||||
else markGroupMembersCIsDeleted user gInfo ms membership
|
||||
APILeaveGroup groupId -> withUser $ \user@User {userId} -> do
|
||||
gInfo@GroupInfo {membership} <- withFastStore $ \db -> getGroupInfo db cxt user groupId
|
||||
filesInfo <- withFastStore' $ \db -> getGroupFileInfo db user gInfo
|
||||
|
||||
@@ -647,6 +647,14 @@ markGroupMembersCIsDeleted user gInfo members byGroupMember = do
|
||||
filesInfo <- withStore' $ \db -> fmap concat $ forM members $ \m -> markGroupMemberCIsDeleted_ db user gInfo m byGroupMember deletedTs
|
||||
cancelFilesInProgress user filesInfo
|
||||
|
||||
-- Reports about a member's messages are authored by the reporter, so deleting the member's own
|
||||
-- chat items never reaches them - they have to be archived separately, as moderation does.
|
||||
archiveMembersReports :: User -> GroupInfo -> [GroupMember] -> GroupMember -> Bool -> CM ()
|
||||
archiveMembersReports user gInfo members byGroupMember byUser = do
|
||||
deletedTs <- liftIO getCurrentTime
|
||||
ciIds <- concat <$> withStore' (\db -> forM members $ \m -> markMemberReportsDeleted db user gInfo m byGroupMember deletedTs)
|
||||
unless (null ciIds) $ toView $ CEvtGroupChatItemsDeleted user gInfo ciIds byUser (Just byGroupMember)
|
||||
|
||||
markGroupMemberCIsDeleted_ :: DB.Connection -> User -> GroupInfo -> GroupMember -> GroupMember -> UTCTime -> IO [CIFileInfo]
|
||||
markGroupMemberCIsDeleted_ db user gInfo member byGroupMember deletedTs = do
|
||||
fs <- getGroupMemberFileInfo db user gInfo member
|
||||
|
||||
@@ -3654,9 +3654,11 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gi' scopeInfo m') msg' brokerTs (CIRcvGroupEvent gEvent)
|
||||
groupMsgToView cInfo ci
|
||||
deleteMessages :: GroupInfo -> GroupMember -> CM ()
|
||||
deleteMessages gInfo' delMem
|
||||
| groupFeatureMemberAllowed SGFFullDelete m gInfo' = deleteGroupMemberCIs user gInfo' delMem
|
||||
| otherwise = markGroupMemberCIsDeleted user gInfo' delMem m
|
||||
deleteMessages gInfo' delMem = do
|
||||
archiveMembersReports user gInfo' [delMem] m False
|
||||
if groupFeatureMemberAllowed SGFFullDelete m gInfo'
|
||||
then deleteGroupMemberCIs user gInfo' delMem
|
||||
else markGroupMemberCIsDeleted user gInfo' delMem m
|
||||
forwardToMember :: GroupMember -> CM ()
|
||||
forwardToMember member =
|
||||
let fwd = GrpMsgForward {fwdSender = FwdMember (memberId' m) (memberShortenedName m), fwdBrokerTs = brokerTs}
|
||||
|
||||
@@ -73,6 +73,7 @@ module Simplex.Chat.Store.Messages
|
||||
markGroupChatItemBlocked,
|
||||
markGroupCIBlockedByAdmin,
|
||||
markMessageReportsDeleted,
|
||||
markMemberReportsDeleted,
|
||||
markReceivedGroupReportsDeleted,
|
||||
deleteLocalChatItem,
|
||||
updateDirectChatItemsRead,
|
||||
@@ -3024,6 +3025,20 @@ markMessageReportsDeleted db User {userId} GroupInfo {groupId} ChatItem {meta =
|
||||
|]
|
||||
(DBCIDeleted, deletedTs, groupMemberId, currentTs, userId, groupId, MCReport_, itemSharedMsgId, DBCINotDeleted)
|
||||
|
||||
markMemberReportsDeleted :: DB.Connection -> User -> GroupInfo -> GroupMember -> GroupMember -> UTCTime -> IO [ChatItemId]
|
||||
markMemberReportsDeleted db User {userId} GroupInfo {groupId} reportedMember byGroupMember deletedTs = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
map fromOnly
|
||||
<$> DB.query
|
||||
db
|
||||
[sql|
|
||||
UPDATE chat_items
|
||||
SET item_deleted = ?, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, updated_at = ?
|
||||
WHERE user_id = ? AND group_id = ? AND msg_content_tag = ? AND quoted_member_id = ? AND item_deleted = ?
|
||||
RETURNING chat_item_id;
|
||||
|]
|
||||
(DBCIDeleted, deletedTs, groupMemberId' byGroupMember, currentTs, userId, groupId, MCReport_, memberId' reportedMember, DBCINotDeleted)
|
||||
|
||||
markReceivedGroupReportsDeleted :: DB.Connection -> User -> GroupInfo -> UTCTime -> IO [ChatItemId]
|
||||
markReceivedGroupReportsDeleted db User {userId} GroupInfo {groupId, membership} deletedTs = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
|
||||
@@ -219,6 +219,7 @@ chatGroupTests = do
|
||||
it "mark member inactive on reaching quota" testGroupMemberInactive
|
||||
describe "group member reports" $ do
|
||||
it "should send report to group owner, admins and moderators, but not other users" testGroupMemberReports
|
||||
it "should archive reports about the messages of the member removed with messages" testGroupMemberReportsRemoveMember
|
||||
describe "group member mentions" $ do
|
||||
it "should send and edit messages with member mentions" testMemberMention
|
||||
it "should forward and quote message updating mentioned member name" testForwardQuoteMention
|
||||
@@ -7390,6 +7391,34 @@ testGroupMemberInactive ps = do
|
||||
}
|
||||
}
|
||||
|
||||
testGroupMemberReportsRemoveMember :: HasCallStack => TestParams -> IO ()
|
||||
testGroupMemberReportsRemoveMember =
|
||||
testChat3 aliceProfile bobProfile cathProfile $
|
||||
\alice bob cath -> do
|
||||
createGroup3' "jokes" alice (bob, GRMember) (cath, GRMember)
|
||||
threadDelay 1000000
|
||||
bob #> "#jokes inappropriate joke"
|
||||
concurrently_
|
||||
(alice <# "#jokes bob> inappropriate joke")
|
||||
(cath <# "#jokes bob> inappropriate joke")
|
||||
cath ##> "/report #jokes content inappropriate joke"
|
||||
cath <# "#jokes (support) > bob inappropriate joke"
|
||||
cath <## " report content"
|
||||
alice <# "#jokes (support: cath) cath> > bob inappropriate joke"
|
||||
alice <## " report content"
|
||||
alice #$> ("/_get chat #1 content=report count=100", chat, [(0, "report content")])
|
||||
cath #$> ("/_get chat #1 content=report count=100", chat, [(1, "report content")])
|
||||
threadDelay 1000000
|
||||
alice ##> "/rm #jokes bob messages=on"
|
||||
alice <## "#jokes: 1 messages deleted by user"
|
||||
alice <## "#jokes: you removed bob from the group with all messages"
|
||||
bob <## "#jokes: alice removed you from the group with all messages"
|
||||
bob <## "use /d #jokes to delete the group"
|
||||
cath <## "#jokes: 1 messages deleted by member alice"
|
||||
cath <## "#jokes: alice removed bob from the group with all messages"
|
||||
alice #$> ("/_get chat #1 content=report count=100", chat, [(0, "report content [marked deleted by you]")])
|
||||
cath #$> ("/_get chat #1 content=report count=100", chat, [(1, "report content [marked deleted by alice]")])
|
||||
|
||||
testGroupMemberReports :: HasCallStack => TestParams -> IO ()
|
||||
testGroupMemberReports =
|
||||
testChat4 aliceProfile bobProfile cathProfile danProfile $
|
||||
|
||||
Reference in new issue
Block a user