mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-22 07:59:48 +00:00
directory: identify registration owner by member id to fix incorrect de-listing
The leave/removed/role-changed handlers identified the registration owner by contact id. A non-owner member can be associated with the owner's contact (via the contact/member merge), so its departure incorrectly de-listed the group. Compare by group member id (owner_member_id) instead, falling back to contact id for registrations recorded before owner_member_id existed.
This commit is contained in:
@@ -54,10 +54,10 @@ data DirectoryEvent
|
||||
| DEPendingMember GroupInfo GroupMember
|
||||
| DEPendingMemberMsg GroupInfo GroupMember ChatItemId Text
|
||||
| DEGroupItemProhibited GroupInfo GroupMember ChatItemId GroupFeature -- a member posted content prohibited by the group's settings
|
||||
| DEContactRoleChanged GroupInfo ContactId GroupMemberRole -- contactId here is the contact whose role changed
|
||||
| DEContactRoleChanged GroupInfo ContactId GroupMemberId GroupMemberRole -- contactId/memberId here identify the member whose role changed
|
||||
| DEServiceRoleChanged GroupInfo GroupMemberRole
|
||||
| DEContactRemovedFromGroup ContactId GroupInfo
|
||||
| DEContactLeftGroup ContactId GroupInfo
|
||||
| DEContactRemovedFromGroup ContactId GroupMemberId GroupInfo
|
||||
| DEContactLeftGroup ContactId GroupMemberId GroupInfo
|
||||
| DEServiceRemovedFromGroup GroupInfo
|
||||
| DEGroupDeleted GroupInfo
|
||||
| DEChatLinkReceived {contact :: Contact, chatItemId :: ChatItemId, chatLink :: MsgChatLink, ownerSig :: Maybe LinkOwnerSig}
|
||||
@@ -93,9 +93,9 @@ crDirectoryEvent_ = \case
|
||||
_ -> Nothing
|
||||
CEvtMemberRole {groupInfo, member, toRole}
|
||||
| groupMemberId' member == groupMemberId' (membership groupInfo) -> Just $ DEServiceRoleChanged groupInfo toRole
|
||||
| otherwise -> (\ctId -> DEContactRoleChanged groupInfo ctId toRole) <$> memberContactId member
|
||||
CEvtDeletedMember {groupInfo, deletedMember} -> (`DEContactRemovedFromGroup` groupInfo) <$> memberContactId deletedMember
|
||||
CEvtLeftMember {groupInfo, member} -> (`DEContactLeftGroup` groupInfo) <$> memberContactId member
|
||||
| otherwise -> (\ctId -> DEContactRoleChanged groupInfo ctId (groupMemberId' member) toRole) <$> memberContactId member
|
||||
CEvtDeletedMember {groupInfo, deletedMember} -> (\ctId -> DEContactRemovedFromGroup ctId (groupMemberId' deletedMember) groupInfo) <$> memberContactId deletedMember
|
||||
CEvtLeftMember {groupInfo, member} -> (\ctId -> DEContactLeftGroup ctId (groupMemberId' member) groupInfo) <$> memberContactId member
|
||||
CEvtDeletedMemberUser {groupInfo} -> Just $ DEServiceRemovedFromGroup groupInfo
|
||||
CEvtGroupDeleted {groupInfo} -> Just $ DEGroupDeleted groupInfo
|
||||
CEvtUnknownMemberAnnounced {groupInfo, unknownMember, announcedMember} -> Just $ DEMemberUpdated {groupInfo, fromMember = unknownMember, toMember = announcedMember}
|
||||
|
||||
@@ -327,10 +327,10 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName
|
||||
DEPendingMember g m -> dePendingMember g m
|
||||
DEPendingMemberMsg g m ciId t -> dePendingMemberMsg g m ciId t
|
||||
DEGroupItemProhibited g m ciId gf -> when prohibitedToObserver $ deGroupItemProhibited g m ciId gf
|
||||
DEContactRoleChanged g ctId role -> deContactRoleChanged g ctId role
|
||||
DEContactRoleChanged g ctId gmId role -> deContactRoleChanged g ctId gmId role
|
||||
DEServiceRoleChanged g role -> deServiceRoleChanged g role
|
||||
DEContactRemovedFromGroup ctId g -> deContactRemovedFromGroup ctId g
|
||||
DEContactLeftGroup ctId g -> deContactLeftGroup ctId g
|
||||
DEContactRemovedFromGroup ctId gmId g -> deContactRemovedFromGroup ctId gmId g
|
||||
DEContactLeftGroup ctId gmId g -> deContactLeftGroup ctId gmId g
|
||||
DEServiceRemovedFromGroup g -> deServiceRemovedFromGroup g
|
||||
DEGroupDeleted g -> deGroupDeleted g
|
||||
DEChatLinkReceived {contact = ct, chatLink, ownerSig} -> deChatLinkReceived ct chatLink ownerSig
|
||||
@@ -354,6 +354,15 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName
|
||||
notifyAdminUsers s = withAdminUsers $ \contactId -> sendMessage' cc contactId s
|
||||
notifyOwner = sendMessage' cc . dbContactId
|
||||
ctId `isOwner` GroupReg {dbContactId} = ctId == dbContactId
|
||||
-- Whether the leaving/removed/role-changed member is the registration owner.
|
||||
-- Comparing by member id (not contact id) is required because a non-owner
|
||||
-- member can be associated with the owner's contact by the probe-and-merge
|
||||
-- mechanism, which would otherwise make its departure de-list the group.
|
||||
-- Registrations recorded before owner_member_id existed keep the contact-id
|
||||
-- comparison.
|
||||
isOwnerMember :: GroupReg -> GroupMemberId -> ContactId -> Bool
|
||||
isOwnerMember GroupReg {dbOwnerMemberId, dbContactId} gmId ctId =
|
||||
maybe (ctId == dbContactId) (== gmId) dbOwnerMemberId
|
||||
withGroupReg :: GroupInfo -> Text -> (GroupReg -> IO ()) -> IO ()
|
||||
withGroupReg GroupInfo {groupId, localDisplayName} err action =
|
||||
getGroupReg cc groupId >>= \case
|
||||
@@ -868,13 +877,13 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName
|
||||
sendToApprove g' gr (n + 1)
|
||||
_ -> pure ()
|
||||
|
||||
deContactRoleChanged :: GroupInfo -> ContactId -> GroupMemberRole -> IO ()
|
||||
deContactRoleChanged g@GroupInfo {groupId, membership = GroupMember {memberRole = serviceRole}} ctId contactRole = do
|
||||
deContactRoleChanged :: GroupInfo -> ContactId -> GroupMemberId -> GroupMemberRole -> IO ()
|
||||
deContactRoleChanged g@GroupInfo {groupId, membership = GroupMember {memberRole = serviceRole}} ctId gmId contactRole = do
|
||||
logInfo $ "contact ID " <> tshow ctId <> " role changed in group " <> viewGroupName g <> " to " <> tshow contactRole
|
||||
withGroupReg g "contact role changed" $ \gr@GroupReg {groupRegStatus} -> do
|
||||
let userGroupRef = userGroupReference gr g
|
||||
uCtRole = "Your role in the group " <> userGroupRef <> " is changed to " <> ctRole
|
||||
when (ctId `isOwner` gr) $
|
||||
when (isOwnerMember gr gmId ctId) $
|
||||
case groupRegStatus of
|
||||
GRSSuspendedBadRoles | rStatus == GRSOk ->
|
||||
setGroupStatus notifyAdminUsers st env cc groupId GRSActive $ \gr' -> do
|
||||
@@ -923,23 +932,23 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName
|
||||
getOwnerGroupMember groupId gr
|
||||
>>= mapM_ (\cm@GroupMember {memberRole} -> when (memberRole == GROwner && memberActive cm) action)
|
||||
|
||||
deContactRemovedFromGroup :: ContactId -> GroupInfo -> IO ()
|
||||
deContactRemovedFromGroup ctId g@GroupInfo {groupId, groupProfile = GroupProfile {publicGroup = pg_}} = do
|
||||
deContactRemovedFromGroup :: ContactId -> GroupMemberId -> GroupInfo -> IO ()
|
||||
deContactRemovedFromGroup ctId gmId g@GroupInfo {groupId, groupProfile = GroupProfile {publicGroup = pg_}} = do
|
||||
let gt = maybe "group" groupTypeStr' pg_
|
||||
logInfo $ "contact ID " <> tshow ctId <> " removed from group " <> viewGroupName g
|
||||
withGroupReg g "contact removed" $ \gr ->
|
||||
when (ctId `isOwner` gr) $
|
||||
when (isOwnerMember gr gmId ctId) $
|
||||
setGroupStatus notifyAdminUsers st env cc groupId GRSRemoved $ \gr' -> do
|
||||
notifyOwner gr' $ "You are removed from the " <> gt <> " " <> userGroupReference gr' g <> ".\n\nThe " <> gt <> " is no longer listed in the directory."
|
||||
notifyAdminUsers $ "The " <> gt <> " " <> groupReference g <> " is de-listed (" <> gt <> " owner is removed)."
|
||||
when (isJust pg_) $ leavePublicGroup g
|
||||
|
||||
deContactLeftGroup :: ContactId -> GroupInfo -> IO ()
|
||||
deContactLeftGroup ctId g@GroupInfo {groupId, groupProfile = GroupProfile {publicGroup = pg_}} = do
|
||||
deContactLeftGroup :: ContactId -> GroupMemberId -> GroupInfo -> IO ()
|
||||
deContactLeftGroup ctId gmId g@GroupInfo {groupId, groupProfile = GroupProfile {publicGroup = pg_}} = do
|
||||
let gt = maybe "group" groupTypeStr' pg_
|
||||
logInfo $ "contact ID " <> tshow ctId <> " left group " <> viewGroupName g
|
||||
withGroupReg g "contact left" $ \gr ->
|
||||
when (ctId `isOwner` gr) $
|
||||
when (isOwnerMember gr gmId ctId) $
|
||||
setGroupStatus notifyAdminUsers st env cc groupId GRSRemoved $ \gr' -> do
|
||||
notifyOwner gr' $ "You left the " <> gt <> " " <> userGroupReference gr' g <> ".\n\nThe " <> gt <> " is no longer listed in the directory."
|
||||
notifyAdminUsers $ "The " <> gt <> " " <> groupReference g <> " is de-listed (" <> gt <> " owner left)."
|
||||
|
||||
Reference in New Issue
Block a user