feat: allow for pending community request state changes
iterates: status-im/status-desktop#11842
This commit is contained in:
parent
a17ee052fb
commit
bb7273cf6f
|
@ -2230,12 +2230,12 @@ func (o *Community) addMemberWithRevealedAccounts(memberKey string, roles []prot
|
|||
return changes
|
||||
}
|
||||
|
||||
func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) error {
|
||||
func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) (adminEventCreated bool, err error) {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
|
||||
if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_REJECT)) {
|
||||
return ErrNotAuthorized
|
||||
return adminEventCreated, ErrNotAuthorized
|
||||
}
|
||||
|
||||
if o.IsControlNode() {
|
||||
|
@ -2252,13 +2252,15 @@ func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) error {
|
|||
CommunityChanges: o.emptyCommunityChanges(),
|
||||
RejectedRequestsToJoin: rejectedRequestsToJoin,
|
||||
}
|
||||
err := o.addNewCommunityEvent(o.ToCommunityRequestToJoinRejectCommunityEvent(adminChanges))
|
||||
err = o.addNewCommunityEvent(o.ToCommunityRequestToJoinRejectCommunityEvent(adminChanges))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return adminEventCreated, err
|
||||
}
|
||||
|
||||
return nil
|
||||
adminEventCreated = true
|
||||
}
|
||||
|
||||
return adminEventCreated, err
|
||||
}
|
||||
|
||||
func (o *Community) ValidateEvent(event *CommunityEvent, signer *ecdsa.PublicKey) error {
|
||||
|
|
|
@ -1424,7 +1424,7 @@ func (m *Manager) handleCommunityDescriptionMessageCommon(community *Community,
|
|||
|
||||
// We mark our requests as completed, though maybe we should mark
|
||||
// any request for any user that has been added as completed
|
||||
if err := m.markRequestToJoin(&m.identity.PublicKey, community); err != nil {
|
||||
if err := m.markRequestToJoinAsAccepted(&m.identity.PublicKey, community); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Check if there's a change and we should be joining
|
||||
|
@ -1702,30 +1702,23 @@ func (m *Manager) handleCommunityEventRequestAccepted(community *Community, comm
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if community.IsControlNode() {
|
||||
// If request to join exists in control node, save request as RequestToJoinStateAccepted
|
||||
// If request to join does not exist in control node, save request as RequestToJoinStateAcceptedPending
|
||||
// as privileged users don't have revealed addresses. This can happen if control node received
|
||||
// community event message before user request to join
|
||||
if existingRequestToJoin != nil {
|
||||
requestToJoin.State = RequestToJoinStateAccepted
|
||||
}
|
||||
} else if community.HasPermissionToSendCommunityEvents() && existingRequestToJoin.State != RequestToJoinStatePending {
|
||||
// the request is already in some pending state or was processed by a control node,
|
||||
// so we won't override it again
|
||||
alreadyProcessedByControlNode := existingRequestToJoin.State == RequestToJoinStateAccepted || existingRequestToJoin.State == RequestToJoinStateDeclined
|
||||
if alreadyProcessedByControlNode || existingRequestToJoin.State == RequestToJoinStateCanceled {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
requestUpdated, err := m.saveOrUpdateRequestToJoin(community.ID(), requestToJoin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If request to join exists in control node, add request to acceptedRequestsToJoin.
|
||||
// Otherwise keep the request as RequestToJoinStateAcceptedPending,
|
||||
// as privileged users don't have revealed addresses. This can happen if control node received
|
||||
// community event message before user request to join.
|
||||
if community.IsControlNode() && requestUpdated {
|
||||
// We only collect requestToJoinIDs which had a state update.
|
||||
// If there wasn't a state update, it means we've seen the request for the first time,
|
||||
// which means we don't have revealed addresses here (as they aren't propagated by
|
||||
// admin nodes), so we don't want to trigger an `AcceptRequestToJoin` in such cases.
|
||||
acceptedRequestsToJoin = append(acceptedRequestsToJoin, requestToJoin.ID)
|
||||
}
|
||||
|
||||
|
@ -1757,24 +1750,21 @@ func (m *Manager) handleCommunityEventRequestRejected(community *Community, comm
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if community.IsControlNode() {
|
||||
// If request to join exists in control node, save request as RequestToJoinStateDeclined
|
||||
// If request to join does not exist in control node, save request as RequestToJoinStateDeclinedPending
|
||||
// as privileged users don't have revealed addresses. This can happen if control node received
|
||||
// community event message before user request to join
|
||||
if existingRequestToJoin != nil {
|
||||
requestToJoin.State = RequestToJoinStateDeclined
|
||||
}
|
||||
} else if community.HasPermissionToSendCommunityEvents() && existingRequestToJoin.State != RequestToJoinStatePending {
|
||||
// the request is already in some pending state or was processed by a control node,
|
||||
// so we won't override it again
|
||||
alreadyProcessedByControlNode := existingRequestToJoin.State == RequestToJoinStateAccepted || existingRequestToJoin.State == RequestToJoinStateDeclined
|
||||
if alreadyProcessedByControlNode || existingRequestToJoin.State == RequestToJoinStateCanceled {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
requestUpdated, err := m.saveOrUpdateRequestToJoin(community.ID(), requestToJoin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If request to join exists in control node, add request to rejectedRequestsToJoin.
|
||||
// Otherwise keep the request as RequestToJoinStateDeclinedPending,
|
||||
// as privileged users don't have revealed addresses. This can happen if control node received
|
||||
// community event message before user request to join.
|
||||
if community.IsControlNode() && requestUpdated {
|
||||
rejectedRequestsToJoin = append(rejectedRequestsToJoin, requestToJoin.ID)
|
||||
}
|
||||
|
@ -1788,9 +1778,9 @@ func (m *Manager) handleCommunityEventRequestRejected(community *Community, comm
|
|||
return requestsToJoin, nil
|
||||
}
|
||||
|
||||
// markRequestToJoin marks all the pending requests to join as completed
|
||||
// markRequestToJoinAsAccepted marks all the pending requests to join as completed
|
||||
// if we are members
|
||||
func (m *Manager) markRequestToJoin(pk *ecdsa.PublicKey, community *Community) error {
|
||||
func (m *Manager) markRequestToJoinAsAccepted(pk *ecdsa.PublicKey, community *Community) error {
|
||||
if community.HasMember(pk) {
|
||||
return m.persistence.SetRequestToJoinState(common.PubkeyToHex(pk), community.ID(), RequestToJoinStateAccepted)
|
||||
}
|
||||
|
@ -1956,34 +1946,6 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if community.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_ACCEPT) && !community.IsControlNode() {
|
||||
if dbRequest.MarkedAsPendingByPrivilegedAccount() {
|
||||
// if the request is in any pending state, it means our admin node has either
|
||||
// already made a decision in the past, or previously received a decision by
|
||||
// another admin, which in both cases means we're not allowed to override this
|
||||
// state again
|
||||
return nil, errors.New("request to join is already in pending state")
|
||||
}
|
||||
|
||||
// admins do not perform permission checks, they merely mark the
|
||||
// request as accepted (pending) and forward their decision to the control node
|
||||
acceptedRequestsToJoin := make(map[string]*protobuf.CommunityRequestToJoin)
|
||||
acceptedRequestsToJoin[dbRequest.PublicKey] = dbRequest.ToCommunityRequestToJoinProtobuf()
|
||||
|
||||
adminChanges := &CommunityEventChanges{
|
||||
AcceptedRequestsToJoin: acceptedRequestsToJoin,
|
||||
}
|
||||
|
||||
err := community.addNewCommunityEvent(community.ToCommunityRequestToJoinAcceptCommunityEvent(adminChanges))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := m.markRequestToJoinAsAcceptedPending(pk, community); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if community.IsControlNode() {
|
||||
revealedAccounts, err := m.persistence.GetRequestToJoinRevealedAddresses(dbRequest.ID)
|
||||
if err != nil {
|
||||
|
@ -2021,17 +1983,10 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err
|
|||
}
|
||||
}
|
||||
|
||||
if err := m.markRequestToJoin(pk, community); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = m.saveAndPublish(community)
|
||||
if err != nil {
|
||||
if err := m.markRequestToJoinAsAccepted(pk, community); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if community.IsControlNode() {
|
||||
if err = m.shareAcceptedRequestToJoinWithPrivilegedMembers(community, dbRequest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2047,6 +2002,31 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
} else if community.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_ACCEPT) {
|
||||
// admins do not perform permission checks, they merely mark the
|
||||
// request as accepted (pending) and forward their decision to the control node
|
||||
acceptedRequestsToJoin := make(map[string]*protobuf.CommunityRequestToJoin)
|
||||
acceptedRequestsToJoin[dbRequest.PublicKey] = dbRequest.ToCommunityRequestToJoinProtobuf()
|
||||
|
||||
adminChanges := &CommunityEventChanges{
|
||||
AcceptedRequestsToJoin: acceptedRequestsToJoin,
|
||||
}
|
||||
|
||||
err := community.addNewCommunityEvent(community.ToCommunityRequestToJoinAcceptCommunityEvent(adminChanges))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := m.markRequestToJoinAsAcceptedPending(pk, community); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, ErrNotAuthorized
|
||||
}
|
||||
|
||||
err = m.saveAndPublish(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return community, nil
|
||||
|
@ -2062,16 +2042,17 @@ func (m *Manager) DeclineRequestToJoin(dbRequest *RequestToJoin) (*Community, er
|
|||
return nil, err
|
||||
}
|
||||
|
||||
requestToJoinState := RequestToJoinStateDeclined
|
||||
if community.HasPermissionToSendCommunityEvents() {
|
||||
requestToJoinState = RequestToJoinStateDeclinedPending
|
||||
}
|
||||
err = m.persistence.SetRequestToJoinState(dbRequest.PublicKey, dbRequest.CommunityID, requestToJoinState)
|
||||
adminEventCreated, err := community.DeclineRequestToJoin(dbRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = community.DeclineRequestToJoin(dbRequest)
|
||||
requestToJoinState := RequestToJoinStateDeclined
|
||||
if adminEventCreated {
|
||||
requestToJoinState = RequestToJoinStateDeclinedPending // can only be declined by control node
|
||||
}
|
||||
|
||||
err = m.persistence.SetRequestToJoinState(dbRequest.PublicKey, dbRequest.CommunityID, requestToJoinState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2146,7 +2127,7 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, receiver
|
|||
|
||||
// don't process request as admin if community is configured as auto-accept
|
||||
if !community.IsControlNode() && community.AcceptRequestToJoinAutomatically() {
|
||||
return nil, errors.New("ignoring request to join, community is set to auto-accept")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// control node must receive requests to join only on community address
|
||||
|
@ -2188,26 +2169,25 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, receiver
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if existingRequestToJoin != nil && existingRequestToJoin.State != RequestToJoinStateCanceled {
|
||||
if existingRequestToJoin == nil || existingRequestToJoin.State == RequestToJoinStateCanceled {
|
||||
if err := m.persistence.SaveRequestToJoin(requestToJoin); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if community.IsControlNode() {
|
||||
// request to join was already processed by an admin and waits to get
|
||||
// confirmation for its decision
|
||||
//
|
||||
// we're only interested in immediately declining any declined/pending
|
||||
// requests here, because if it's accepted/pending, we still need to perform
|
||||
// some checks
|
||||
if existingRequestToJoin.State == RequestToJoinStateDeclinedPending {
|
||||
if community.IsControlNode() {
|
||||
if existingRequestToJoin != nil && existingRequestToJoin.State == RequestToJoinStateDeclinedPending {
|
||||
requestToJoin.State = RequestToJoinStateDeclined
|
||||
}
|
||||
return requestToJoin, nil
|
||||
}
|
||||
} else {
|
||||
if err := m.persistence.SaveRequestToJoin(requestToJoin); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(request.RevealedAccounts) > 0 && community.IsControlNode() {
|
||||
if len(request.RevealedAccounts) > 0 {
|
||||
// verify if revealed addresses indeed belong to requester
|
||||
for _, revealedAccount := range request.RevealedAccounts {
|
||||
recoverParams := account.RecoverParams{
|
||||
|
@ -2239,43 +2219,20 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, receiver
|
|||
// It may happen when member removes itself from community and then tries to rejoin
|
||||
// More specifically, CommunityRequestToLeave may be delivered later than CommunityRequestToJoin, or not delivered at all
|
||||
acceptAutomatically := community.AcceptRequestToJoinAutomatically() || community.HasMember(signer)
|
||||
if acceptAutomatically {
|
||||
if community.IsControlNode() {
|
||||
err = m.markRequestToJoin(signer, community)
|
||||
// If the request to join was already accepted by another admin,
|
||||
// we mark it as accepted so it won't be in pending state, even if the community
|
||||
// is not set to auto-accept
|
||||
acceptedByAdmin := existingRequestToJoin != nil && existingRequestToJoin.State == RequestToJoinStateAcceptedPending
|
||||
if acceptAutomatically || acceptedByAdmin {
|
||||
err = m.markRequestToJoinAsAccepted(signer, community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Don't check permissions here,
|
||||
// it will be done further in the processing pipeline.
|
||||
requestToJoin.State = RequestToJoinStateAccepted
|
||||
} else {
|
||||
err = m.markRequestToJoinAsAcceptedPending(signer, community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
requestToJoin.State = RequestToJoinStateAcceptedPending
|
||||
}
|
||||
return requestToJoin, nil
|
||||
}
|
||||
|
||||
if community.IsControlNode() && len(request.RevealedAccounts) > 0 {
|
||||
permissionsSatisfied, _, err := m.accountsSatisfyPermissionsToJoin(community, request.RevealedAccounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !permissionsSatisfied {
|
||||
requestToJoin.State = RequestToJoinStateDeclined
|
||||
}
|
||||
if permissionsSatisfied && existingRequestToJoin != nil && existingRequestToJoin.State == RequestToJoinStateAcceptedPending {
|
||||
err = m.markRequestToJoin(signer, community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// if the request to join was already accepted by another admin,
|
||||
// we mark it as accepted so it won't be in pending state, even if the community
|
||||
// is not set to auto-accept
|
||||
requestToJoin.State = RequestToJoinStateAccepted
|
||||
}
|
||||
}
|
||||
|
||||
return requestToJoin, nil
|
||||
|
@ -2882,7 +2839,7 @@ func (m *Manager) HandleCommunityRequestToJoinResponse(signer *ecdsa.PublicKey,
|
|||
}
|
||||
|
||||
if request.Accepted {
|
||||
err = m.markRequestToJoin(&m.identity.PublicKey, community)
|
||||
err = m.markRequestToJoinAsAccepted(&m.identity.PublicKey, community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -74,10 +74,6 @@ func (r *RequestToJoin) Empty() bool {
|
|||
return len(r.ID)+len(r.PublicKey)+int(r.Clock)+len(r.ENSName)+len(r.ChatID)+len(r.CommunityID)+int(r.State) == 0
|
||||
}
|
||||
|
||||
func (r *RequestToJoin) MarkedAsPendingByPrivilegedAccount() bool {
|
||||
return r.State == RequestToJoinStateAcceptedPending || r.State == RequestToJoinStateDeclinedPending
|
||||
}
|
||||
|
||||
func AddTimeoutToRequestToJoinClock(clock uint64) (uint64, error) {
|
||||
requestToJoinClock, err := strconv.ParseInt(fmt.Sprint(clock), 10, 64)
|
||||
if err != nil {
|
||||
|
|
|
@ -147,15 +147,6 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRejectMemberRequ
|
|||
testRejectMemberRequestToJoin(s, community, user)
|
||||
}
|
||||
|
||||
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRequestToJoinStateCannotBeOverridden() {
|
||||
additionalOwner := s.newMessenger("", []string{})
|
||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
|
||||
|
||||
// set up additional user that will send request to join
|
||||
user := s.newMessenger("", []string{})
|
||||
testEventSenderCannotOverrideRequestToJoinState(s, community, user, additionalOwner)
|
||||
}
|
||||
|
||||
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
|
||||
additionalOwner := s.newMessenger("", []string{})
|
||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
|
||||
|
|
|
@ -168,15 +168,6 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJo
|
|||
testRejectMemberRequestToJoin(s, community, user)
|
||||
}
|
||||
|
||||
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRequestToJoinStateCannotBeOverridden() {
|
||||
additionalTokenMaster := s.newMessenger("", []string{})
|
||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
|
||||
|
||||
// set up additional user that will send request to join
|
||||
user := s.newMessenger("", []string{})
|
||||
testEventSenderCannotOverrideRequestToJoinState(s, community, user, additionalTokenMaster)
|
||||
}
|
||||
|
||||
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
|
||||
additionalTokenMaster := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
|
||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
|
||||
|
|
|
@ -1211,6 +1211,26 @@ func testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu
|
|||
s.Require().NoError(err)
|
||||
s.Require().Len(acceptedPendingRequests, 1)
|
||||
s.Require().Equal(acceptedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
||||
|
||||
// event sender 1 changes its mind and rejects the request
|
||||
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
||||
response, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(response)
|
||||
|
||||
// event sender 2 receives updated decision of other event sender
|
||||
_, err = WaitOnMessengerResponse(
|
||||
additionalEventSender,
|
||||
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
||||
"event sender did not receive community request to join",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// at this point, the request to join is in declined/pending state for event sender 2
|
||||
rejectedPendingRequests, err := additionalEventSender.DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(rejectedPendingRequests, 1)
|
||||
s.Require().Equal(rejectedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
||||
}
|
||||
|
||||
func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
||||
|
@ -1269,6 +1289,27 @@ func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu
|
|||
s.Require().NoError(err)
|
||||
s.Require().Len(rejectedPendingRequests, 1)
|
||||
s.Require().Equal(rejectedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
||||
|
||||
// event sender 1 changes its mind and accepts the request
|
||||
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
||||
response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().Len(response.Communities(), 1)
|
||||
|
||||
// event sender 2 receives updated decision of other event sender
|
||||
_, err = WaitOnMessengerResponse(
|
||||
additionalEventSender,
|
||||
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
||||
"event sender did not receive community request to join",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// at this point, the request to join is in accepted/pending state for event sender 2
|
||||
acceptedPendingRequests, err := additionalEventSender.AcceptedPendingRequestsToJoinForCommunity(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(acceptedPendingRequests, 1)
|
||||
s.Require().Equal(acceptedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
||||
}
|
||||
|
||||
func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
|
||||
|
@ -1367,78 +1408,6 @@ func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community
|
|||
s.Require().Len(declinedRequestsPending, 0)
|
||||
}
|
||||
|
||||
func testEventSenderCannotOverrideRequestToJoinState(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
||||
_, err := user.Start()
|
||||
|
||||
s := base.GetSuite()
|
||||
s.Require().NoError(err)
|
||||
defer user.Shutdown() // nolint: errcheck
|
||||
|
||||
advertiseCommunityTo(s, community, base.GetControlNode(), user)
|
||||
|
||||
// user sends request to join
|
||||
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
||||
response, err := user.RequestToJoinCommunity(requestToJoin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
||||
|
||||
sentRequest := response.RequestsToJoinCommunity[0]
|
||||
|
||||
// event sender receives request to join
|
||||
_, err = WaitOnMessengerResponse(
|
||||
base.GetEventSender(),
|
||||
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
||||
"event sender did not receive community request to join",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// event sender 2 receives request to join
|
||||
_, err = WaitOnMessengerResponse(
|
||||
additionalEventSender,
|
||||
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
||||
"event sender did not receive community request to join",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
||||
|
||||
// request is pending for event sener 2
|
||||
pendingRequests, err := additionalEventSender.PendingRequestsToJoinForCommunity(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(pendingRequests)
|
||||
s.Require().Len(pendingRequests, 1)
|
||||
|
||||
// event sender 1 rejects request to join
|
||||
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
||||
_, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// request to join is now marked as rejected pending for event sender 1
|
||||
rejectedPendingRequests, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(rejectedPendingRequests)
|
||||
s.Require().Len(rejectedPendingRequests, 1)
|
||||
|
||||
// event sender 2 receives event sender 1's decision
|
||||
_, err = WaitOnMessengerResponse(
|
||||
additionalEventSender,
|
||||
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
||||
"event sender did not receive community request to join",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// request to join is now marked as rejected pending for event sender 2
|
||||
rejectedPendingRequests, err = additionalEventSender.DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(rejectedPendingRequests)
|
||||
s.Require().Len(rejectedPendingRequests, 1)
|
||||
|
||||
// event sender 2 should not be able to override that pending state
|
||||
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
||||
_, err = additionalEventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
||||
s.Require().Error(err)
|
||||
}
|
||||
|
||||
func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
||||
_, err := user.Start()
|
||||
|
||||
|
|
|
@ -175,15 +175,6 @@ func (s *AdminCommunityEventsSuite) TestAdminRejectMemberRequestToJoin() {
|
|||
testRejectMemberRequestToJoin(s, community, user)
|
||||
}
|
||||
|
||||
func (s *AdminCommunityEventsSuite) TestAdminRequestToJoinStateCannotBeOverridden() {
|
||||
additionalAdmin := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
|
||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
|
||||
|
||||
// set up additional user that will send request to join
|
||||
user := s.newMessenger("", []string{})
|
||||
testEventSenderCannotOverrideRequestToJoinState(s, community, user, additionalAdmin)
|
||||
}
|
||||
|
||||
func (s *AdminCommunityEventsSuite) TestAdminControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
|
||||
additionalAdmin := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
|
||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
|
||||
|
@ -402,7 +393,7 @@ func (s *AdminCommunityEventsSuite) TestAdminDoesNotHaveRejectedEventsLoop() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Update community clock without publishing new CommunityDescription
|
||||
err = community.DeclineRequestToJoin(nil)
|
||||
_, err = community.DeclineRequestToJoin(nil)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.owner.communitiesManager.SaveCommunity(community)
|
||||
|
|
|
@ -1435,8 +1435,12 @@ func (m *Messenger) HandleCommunityRequestToJoin(state *ReceivedMessageState, re
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// not interested, stop further processing
|
||||
if requestToJoin == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if requestToJoin.State == communities.RequestToJoinStateAccepted || requestToJoin.State == communities.RequestToJoinStateAcceptedPending {
|
||||
if requestToJoin.State == communities.RequestToJoinStateAccepted {
|
||||
accept := &requests.AcceptRequestToJoinCommunity{
|
||||
ID: requestToJoin.ID,
|
||||
}
|
||||
|
@ -1452,7 +1456,7 @@ func (m *Messenger) HandleCommunityRequestToJoin(state *ReceivedMessageState, re
|
|||
}
|
||||
}
|
||||
|
||||
if requestToJoin.State == communities.RequestToJoinStateDeclined || requestToJoin.State == communities.RequestToJoinStateDeclinedPending {
|
||||
if requestToJoin.State == communities.RequestToJoinStateDeclined {
|
||||
cancel := &requests.DeclineRequestToJoinCommunity{
|
||||
ID: requestToJoin.ID,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue