mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-11 18:17:46 +00:00
core: directory bot must not admit members past admission review
APIAcceptMember chose between "advance a pending member per group policy" and "a moderator admits a member past admission review" using only the member's current status. The directory bot is a group admin and called the same command, so when a member was already pending review at the moment the bot's approval ran (a prior approval by the bot itself, from a queued event, already advanced them), the bot's approval silently ran the full-admit branch - admitting the member past admission review (visible to everyone, able to send) in a plain p2p group with review still correctly enabled. Add screeningApproval to APIAcceptMember: the directory bot passes True and can only advance a pending-approval member per policy, never admit past review (a no-op on a pending-review member); human moderators (screeningApproval=False, the default; screening=on in the parser sets True) keep the full behaviour. Backward compatible - apps send /_accept member as a string command.
This commit is contained in:
1 parent
139ce5f8cc
commit
df36fc8c4a
6 files changed
+102
-6
No files matched your search
@@ -471,7 +471,7 @@ data ChatCommand
|
||||
| APIAddMember {groupId :: GroupId, contactId :: ContactId, memberRole :: GroupMemberRole}
|
||||
| APIAddMemberViaGroup {groupId :: GroupId, viaGroupId :: GroupId, groupMemberId :: GroupMemberId, memberRole :: GroupMemberRole}
|
||||
| APIJoinGroup {groupId :: GroupId, enableNtfs :: MsgFilter}
|
||||
| APIAcceptMember {groupId :: GroupId, groupMemberId :: GroupMemberId, memberRole :: GroupMemberRole}
|
||||
| APIAcceptMember {groupId :: GroupId, groupMemberId :: GroupMemberId, memberRole :: GroupMemberRole, screeningApproval :: Bool}
|
||||
| APIDeleteMemberSupportChat GroupId GroupMemberId
|
||||
| APIMembersRole {groupId :: GroupId, groupMemberIds :: NonEmpty GroupMemberId, memberRole :: GroupMemberRole}
|
||||
| APIBlockMembersForAll {groupId :: GroupId, groupMemberIds :: NonEmpty GroupMemberId, blocked :: Bool}
|
||||
|
||||
@@ -2919,7 +2919,7 @@ processChatCommand cxt nm = \case
|
||||
e -> eToView e
|
||||
pure $ CRUserAcceptedGroupSent user g {membership = membership {memberStatus = GSMemAccepted}} Nothing
|
||||
Left ct -> throwChatError $ CEContactNotActive ct
|
||||
APIAcceptMember groupId gmId role -> withUser $ \user@User {userId} -> do
|
||||
APIAcceptMember groupId gmId role screeningApproval -> withUser $ \user@User {userId} -> do
|
||||
(g@(GIK gInfo _), m) <- withFastStore $ \db -> (,) <$> getGroupInfoKeys db cxt user groupId <*> getGroupMemberById db cxt user gmId
|
||||
-- same rule as role change (moderators grant up to member); pending member's role is a stand-in, so treat it as member
|
||||
assertUserGroupRole gInfo $ roleRequiredToChange GRMember role
|
||||
@@ -2950,6 +2950,8 @@ processChatCommand cxt nm = \case
|
||||
createInternalChatItem user (CDGroupSnd gInfo' scopeInfo) (CISndGroupEvent gEvent) Nothing
|
||||
pure $ CRMemberAccepted user gInfo' m'
|
||||
Nothing -> throwChatError CEGroupMemberNotActive
|
||||
-- admitting past review is a moderator decision, not a screening one (e.g. directory bot captcha)
|
||||
GSMemPendingReview | screeningApproval -> pure $ CRMemberAccepted user gInfo m
|
||||
GSMemPendingReview -> do
|
||||
let scope = Just $ GCSMemberSupport $ Just (groupMemberId' m)
|
||||
modMs <- withFastStore' $ \db -> getGroupModerators db cxt user gInfo
|
||||
@@ -3300,7 +3302,7 @@ processChatCommand cxt nm = \case
|
||||
JoinGroup gName enableNtfs -> withUser $ \user -> do
|
||||
groupId <- withFastStore $ \db -> getGroupIdByName db user gName
|
||||
processChatCommand cxt nm $ APIJoinGroup groupId enableNtfs
|
||||
AcceptMember gName gMemberName memRole -> withMemberName gName gMemberName $ \gId gMemberId -> APIAcceptMember gId gMemberId memRole
|
||||
AcceptMember gName gMemberName memRole -> withMemberName gName gMemberName $ \gId gMemberId -> APIAcceptMember gId gMemberId memRole False
|
||||
MemberRole gName gMemberName memRole -> withMemberName gName gMemberName $ \gId gMemberId -> APIMembersRole gId [gMemberId] memRole
|
||||
BlockForAll gName gMemberName blocked -> withMemberName gName gMemberName $ \gId gMemberId -> APIBlockMembersForAll gId [gMemberId] blocked
|
||||
RemoveMembers gName gMemberNames withMessages -> withUser $ \user -> do
|
||||
@@ -6416,7 +6418,7 @@ chatCommandP =
|
||||
"/_add #" *> (APIAddMember <$> A.decimal <* A.space <*> A.decimal <*> memberRole),
|
||||
"/_add #" *> (APIAddMemberViaGroup <$> A.decimal <* " #" <*> A.decimal <* A.space <*> A.decimal <*> memberRole),
|
||||
"/_join #" *> (APIJoinGroup <$> A.decimal <*> pure MFAll), -- needs to be changed to support in UI
|
||||
"/_accept member #" *> (APIAcceptMember <$> A.decimal <* A.space <*> A.decimal <*> memberRole),
|
||||
"/_accept member #" *> (APIAcceptMember <$> A.decimal <* A.space <*> A.decimal <*> memberRole <*> (" screening=" *> onOffP <|> pure False)),
|
||||
"/_delete member chat #" *> (APIDeleteMemberSupportChat <$> A.decimal <* A.space <*> A.decimal),
|
||||
"/_member role #" *> (APIMembersRole <$> A.decimal <*> _strP <*> memberRole),
|
||||
"/_block #" *> (APIBlockMembersForAll <$> A.decimal <*> _strP <* " blocked=" <*> onOffP),
|
||||
|
||||
Reference in new issue
Block a user