This commit is contained in:
spaced4ndy committed 2026-05-28 19:15:31 +04:00
1 parent ca7ddc7278
commit 779a8a7cff
7 files changed
+107 -72

No files matched your search

+4 -3
View File
@@ -1182,7 +1182,8 @@ introduceInChannel _ _ _ GroupMember {activeConn = Nothing} = throwChatError $ C
introduceInChannel vr user gInfo subscriber@GroupMember {activeConn = Just conn, indexInGroup = subscriberIdx} = do
-- roster first, so the joiner trusts mod/admin keys before relay intros
forwardCachedRoster user gInfo subscriber
modMs <- withStore' $ \db -> getGroupModerators db vr user gInfo
-- filter to current members so left/removed mods/admins aren't re-introduced to the joiner
modMs <- filter memberCurrent <$> withStore' (\db -> getGroupModerators db vr user gInfo)
void $ sendGroupMessage' user gInfo modMs $ XGrpMemNew (memberInfo gInfo subscriber) Nothing
withStore' $ \db ->
setMemberVectorNewRelations db subscriber [(indexInGroup m, (IDSubjectIntroduced, MRIntroduced)) | m <- modMs]
@@ -2143,7 +2144,7 @@ bumpAndBroadcastRoster user gInfo
let rosterVer = maybe 0 (+ 1) (rosterVersion gInfo)
(relays, roster) <- withStore' $ \db -> do
relays <- getGroupRelayMembers db vr user gInfo
mods <- getGroupModsNoOwners db vr user gInfo
mods <- getGroupRosterMembers db vr user gInfo
setGroupRosterVersion db gInfo rosterVer
pure (relays, buildGroupRoster rosterVer mods)
forM_ (L.nonEmpty relays) $ \relays' ->
@@ -2154,7 +2155,7 @@ sendGroupRosterToRelay :: User -> GroupInfo -> GroupMember -> CM ()
sendGroupRosterToRelay user gInfo relayMember =
forM_ (rosterVersion gInfo) $ \rosterVer -> do
vr <- chatVersionRange
mods <- withStore' $ \db -> getGroupModsNoOwners db vr user gInfo
mods <- withStore' $ \db -> getGroupRosterMembers db vr user gInfo
void $ sendGroupMessage' user gInfo [relayMember] (XGrpRoster (buildGroupRoster rosterVer mods))
sendGroupMessages :: MsgEncodingI e => User -> GroupInfo -> Maybe GroupChatScope -> ShowGroupAsSender -> [GroupMember] -> NonEmpty (ChatMsgEvent e) -> CM (NonEmpty (Either ChatError SndMessage), GroupSndResult)
+8 -2
View File
@@ -3129,7 +3129,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
| otherwise =
withStore' (\db -> runExceptT $ getGroupMemberByMemberId db vr user gInfo memId) >>= \case
Right member -> changeMemberRole gInfo member $ RGEMemberRole (groupMemberId' member) (fromLocalProfile $ memberProfile member) memRole
Left _ -> messageError "x.grp.mem.role with unknown member ID" $> Nothing
-- in relay groups the roster delivers the (privileged) member separately; no-op until then
Left _
| useRelays' gInfo -> pure Nothing
| otherwise -> messageError "x.grp.mem.role with unknown member ID" $> Nothing
where
GroupMember {memberId = membershipMemId} = membership
changeMemberRole gInfo' member@GroupMember {memberRole = fromRole} gEvent
@@ -3176,7 +3179,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
warnings <- withStore' $ \db -> do
warnings <- forM entries (applyRosterEntryDB db)
-- absent privileged members revert to the joiner default
currentPriv <- getGroupModsNoOwners db vr user gInfo
currentPriv <- getGroupRosterMembers db vr user gInfo
forM_ currentPriv $ \m ->
when (memberId' m `notElem` rosterIds) $
updateGroupMemberRole db user m defaultRole
@@ -3340,6 +3343,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo''' scopeInfo m') msg brokerTs (CIRcvGroupEvent RGEMemberLeft)
groupMsgToView cInfo ci
toView $ CEvtLeftMember user gInfo''' m' {memberStatus = GSMemLeft} msgSigned
-- a privileged leaver drops out of the roster; bumpAndBroadcastRoster is owner-guarded
when (useRelays' gInfo'' && isRosterRole (memberRole' m)) $
bumpAndBroadcastRoster user gInfo'' `catchAllErrors` eToView
pure $ memberEventDeliveryScope m
xGrpDel :: GroupInfo -> GroupMember -> RcvMessage -> UTCTime -> CM ()
+7 -6
View File
@@ -67,7 +67,7 @@ module Simplex.Chat.Store.Groups
getGroupMembersByIndexes,
getSupportScopeMembersByIndexes,
getGroupModerators,
getGroupModsNoOwners,
getGroupRosterMembers,
getGroupRelayMembers,
getGroupMembersForExpiration,
getRemovedMembersToCleanup,
@@ -1205,11 +1205,12 @@ getGroupModerators db vr user@User {userId, userContactId} GroupInfo {groupId} =
(groupMemberQuery <> " WHERE m.user_id = ? AND m.group_id = ? AND (m.contact_id IS NULL OR m.contact_id != ?) AND m.member_role IN (?,?,?)")
(userId, groupId, userContactId, GRModerator, GRAdmin, GROwner)
-- Moderators and admins only, excluding owners. Use for roster-related paths
-- where owners must not be touched (owners are link-anchored, not roster-managed).
getGroupModsNoOwners :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> IO [GroupMember]
getGroupModsNoOwners db vr user@User {userId, userContactId} GroupInfo {groupId} = do
map (toContactMember vr user)
-- Moderators and admins only, excluding owners and non-current members.
-- Used for roster-related paths where owners must not be touched (owners are
-- link-anchored), and left/removed members must not appear in the cached roster.
getGroupRosterMembers :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> IO [GroupMember]
getGroupRosterMembers db vr user@User {userId, userContactId} GroupInfo {groupId} = do
filter memberCurrent . map (toContactMember vr user)
<$> DB.query
db
(groupMemberQuery <> " WHERE m.user_id = ? AND m.group_id = ? AND (m.contact_id IS NULL OR m.contact_id != ?) AND m.member_role IN (?,?)")