mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-16 19:13:25 +00:00
wip
This commit is contained in:
@@ -1180,18 +1180,21 @@ forwardCachedRoster user gInfo subscriber = do
|
||||
introduceInChannel :: VersionRangeChat -> User -> GroupInfo -> GroupMember -> CM ()
|
||||
introduceInChannel _ _ _ GroupMember {activeConn = Nothing} = throwChatError $ CEInternalError "member connection not active"
|
||||
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
|
||||
-- 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)
|
||||
(owners, rosterMems) <- withStore' $ \db ->
|
||||
(,) <$> getGroupOwners db vr user gInfo <*> getGroupRosterMembers db vr user gInfo
|
||||
let modMs = owners <> rosterMems
|
||||
void $ sendGroupMessage' user gInfo modMs $ XGrpMemNew (memberInfo gInfo subscriber) Nothing
|
||||
withStore' $ \db ->
|
||||
setMemberVectorNewRelations db subscriber [(indexInGroup m, (IDSubjectIntroduced, MRIntroduced)) | m <- modMs]
|
||||
let introEvts = map (memberIntroEvt gInfo) modMs
|
||||
forM_ (L.nonEmpty introEvts) $ \introEvts' ->
|
||||
sendGroupMemberMessages user gInfo conn introEvts'
|
||||
-- owner intros first so the joiner has the owner profile loaded before applying the cached roster (signed by the owner)
|
||||
sendIntros owners
|
||||
forwardCachedRoster user gInfo subscriber
|
||||
sendIntros rosterMems
|
||||
withStore' $ \db ->
|
||||
setMembersVectorsNewRelation db modMs subscriberIdx IDSubjectIntroduced MRIntroduced
|
||||
where
|
||||
sendIntros ms = forM_ (L.nonEmpty $ map (memberIntroEvt gInfo) ms) $ \evts ->
|
||||
sendGroupMemberMessages user gInfo conn evts
|
||||
|
||||
userProfileInGroup :: User -> GroupInfo -> Maybe Profile -> Profile
|
||||
userProfileInGroup user = userProfileInGroup' user . groupFeatureUserAllowed SGFSimplexLinks
|
||||
@@ -1228,8 +1231,8 @@ isRosterRole r = r == GRModerator || r == GRAdmin
|
||||
|
||||
-- Drop non-privileged-role entries and de-duplicate by memberId, keeping the first.
|
||||
validateGroupRoster :: GroupRoster -> GroupRoster
|
||||
validateGroupRoster GroupRoster {version, roster = entries} =
|
||||
GroupRoster {version, roster = dedup [] $ filter (\RosterMember {role} -> isRosterRole role) entries}
|
||||
validateGroupRoster GroupRoster {version = ver, roster = entries} =
|
||||
GroupRoster {version = ver, roster = dedup [] $ filter (\RosterMember {role} -> isRosterRole role) entries}
|
||||
where
|
||||
dedup _ [] = []
|
||||
dedup seen (rm@RosterMember {memberId} : rms)
|
||||
|
||||
@@ -68,6 +68,7 @@ module Simplex.Chat.Store.Groups
|
||||
getSupportScopeMembersByIndexes,
|
||||
getGroupModerators,
|
||||
getGroupRosterMembers,
|
||||
getGroupOwners,
|
||||
getGroupRelayMembers,
|
||||
getGroupMembersForExpiration,
|
||||
getRemovedMembersToCleanup,
|
||||
@@ -1215,6 +1216,14 @@ getGroupRosterMembers 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)
|
||||
|
||||
getGroupOwners :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> IO [GroupMember]
|
||||
getGroupOwners 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 = ?")
|
||||
(userId, groupId, userContactId, GROwner)
|
||||
|
||||
getGroupRelayMembers :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> IO [GroupMember]
|
||||
getGroupRelayMembers db vr user@User {userId, userContactId} GroupInfo {groupId} = do
|
||||
map (toContactMember vr user)
|
||||
|
||||
+22
-14
@@ -9646,30 +9646,38 @@ testChannelRoleTransitionsUpdateRoster ps =
|
||||
withNewTestChat ps "eve" eveProfile $ \eve ->
|
||||
withNewTestChat ps "frank" frankProfile $ \frank -> do
|
||||
(shortLink, fullLink) <- prepareChannel1Relay "team" alice bob
|
||||
forM_ [cath, dan, eve] $ \member ->
|
||||
memberJoinChannel "team" [bob] [alice] shortLink fullLink member
|
||||
-- member -> moderator: dan/eve XGrpMemRole skipped; roster apply creates cath and emits chat item
|
||||
threadDelay 1000000
|
||||
memberJoinChannel "team" [bob] [alice] shortLink fullLink cath
|
||||
-- member -> moderator
|
||||
threadDelay 100000
|
||||
alice ##> "/mr #team cath moderator"
|
||||
alice <## "#team: you changed the role of cath to moderator (signed)"
|
||||
concurrentlyN_
|
||||
[ bob <## "#team: alice changed the role of cath from member to moderator (signed)",
|
||||
cath <## "#team: alice changed your role from member to moderator (signed)",
|
||||
dan <## "#team: alice changed the role of cath from member to moderator (signed)",
|
||||
eve <## "#team: alice changed the role of cath from member to moderator (signed)"
|
||||
cath <## "#team: alice changed your role from member to moderator (signed)"
|
||||
]
|
||||
-- moderator -> admin (within roster): dan/eve now know cath, so role event lands cleanly
|
||||
threadDelay 1000000
|
||||
-- dan joins; cached roster has cath as moderator
|
||||
threadDelay 100000
|
||||
memberJoinChannel "team" [bob] [alice, cath] shortLink fullLink dan
|
||||
dan <## "#team: alice changed the role of cath from member to moderator (signed)"
|
||||
threadDelay 100000
|
||||
checkMemberRow dan "cath" (Just "moderator")
|
||||
-- moderator -> admin: dan now knows cath, role event lands cleanly
|
||||
threadDelay 100000
|
||||
alice ##> "/mr #team cath admin"
|
||||
alice <## "#team: you changed the role of cath to admin (signed)"
|
||||
concurrentlyN_
|
||||
[ bob <## "#team: alice changed the role of cath from moderator to admin (signed)",
|
||||
cath <## "#team: alice changed your role from moderator to admin (signed)",
|
||||
dan <## "#team: alice changed the role of cath from moderator to admin (signed)",
|
||||
eve <## "#team: alice changed the role of cath from moderator to admin (signed)"
|
||||
dan <## "#team: alice changed the role of cath from moderator to admin (signed)"
|
||||
]
|
||||
-- eve joins; cached roster has cath as admin
|
||||
threadDelay 100000
|
||||
memberJoinChannel "team" [bob] [alice, cath] shortLink fullLink eve
|
||||
eve <## "#team: alice changed the role of cath from member to admin (signed)"
|
||||
threadDelay 100000
|
||||
checkMemberRow eve "cath" (Just "admin")
|
||||
-- admin -> member (crossing out of roster): roster drops cath
|
||||
threadDelay 1000000
|
||||
threadDelay 100000
|
||||
alice ##> "/mr #team cath member"
|
||||
alice <## "#team: you changed the role of cath to member (signed)"
|
||||
concurrentlyN_
|
||||
@@ -9678,8 +9686,8 @@ testChannelRoleTransitionsUpdateRoster ps =
|
||||
dan <## "#team: alice changed the role of cath from admin to member (signed)",
|
||||
eve <## "#team: alice changed the role of cath from admin to member (signed)"
|
||||
]
|
||||
-- frank joins; cath never posted, and isn't in the roster, so frank has no record of her
|
||||
threadDelay 1000000
|
||||
-- frank joins; cath isn't in the roster, so frank has no record of her
|
||||
threadDelay 100000
|
||||
memberJoinChannel "team" [bob] [alice] shortLink fullLink frank
|
||||
threadDelay 100000
|
||||
checkMemberRow frank "cath" Nothing
|
||||
|
||||
Reference in New Issue
Block a user