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
|
return changes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) error {
|
func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) (adminEventCreated bool, err error) {
|
||||||
o.mutex.Lock()
|
o.mutex.Lock()
|
||||||
defer o.mutex.Unlock()
|
defer o.mutex.Unlock()
|
||||||
|
|
||||||
if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_REJECT)) {
|
if !(o.IsControlNode() || o.hasPermissionToSendCommunityEvent(protobuf.CommunityEvent_COMMUNITY_REQUEST_TO_JOIN_REJECT)) {
|
||||||
return ErrNotAuthorized
|
return adminEventCreated, ErrNotAuthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.IsControlNode() {
|
if o.IsControlNode() {
|
||||||
|
@ -2252,13 +2252,15 @@ func (o *Community) DeclineRequestToJoin(dbRequest *RequestToJoin) error {
|
||||||
CommunityChanges: o.emptyCommunityChanges(),
|
CommunityChanges: o.emptyCommunityChanges(),
|
||||||
RejectedRequestsToJoin: rejectedRequestsToJoin,
|
RejectedRequestsToJoin: rejectedRequestsToJoin,
|
||||||
}
|
}
|
||||||
err := o.addNewCommunityEvent(o.ToCommunityRequestToJoinRejectCommunityEvent(adminChanges))
|
err = o.addNewCommunityEvent(o.ToCommunityRequestToJoinRejectCommunityEvent(adminChanges))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return adminEventCreated, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adminEventCreated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return adminEventCreated, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) ValidateEvent(event *CommunityEvent, signer *ecdsa.PublicKey) error {
|
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
|
// We mark our requests as completed, though maybe we should mark
|
||||||
// any request for any user that has been added as completed
|
// 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
|
return nil, err
|
||||||
}
|
}
|
||||||
// Check if there's a change and we should be joining
|
// Check if there's a change and we should be joining
|
||||||
|
@ -1702,18 +1702,11 @@ func (m *Manager) handleCommunityEventRequestAccepted(community *Community, comm
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if community.IsControlNode() {
|
if existingRequestToJoin != nil {
|
||||||
// If request to join exists in control node, save request as RequestToJoinStateAccepted
|
alreadyProcessedByControlNode := existingRequestToJoin.State == RequestToJoinStateAccepted || existingRequestToJoin.State == RequestToJoinStateDeclined
|
||||||
// If request to join does not exist in control node, save request as RequestToJoinStateAcceptedPending
|
if alreadyProcessedByControlNode || existingRequestToJoin.State == RequestToJoinStateCanceled {
|
||||||
// as privileged users don't have revealed addresses. This can happen if control node received
|
continue
|
||||||
// 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
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requestUpdated, err := m.saveOrUpdateRequestToJoin(community.ID(), requestToJoin)
|
requestUpdated, err := m.saveOrUpdateRequestToJoin(community.ID(), requestToJoin)
|
||||||
|
@ -1721,11 +1714,11 @@ func (m *Manager) handleCommunityEventRequestAccepted(community *Community, comm
|
||||||
return nil, err
|
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 {
|
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)
|
acceptedRequestsToJoin = append(acceptedRequestsToJoin, requestToJoin.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1757,24 +1750,21 @@ func (m *Manager) handleCommunityEventRequestRejected(community *Community, comm
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if community.IsControlNode() {
|
if existingRequestToJoin != nil {
|
||||||
// If request to join exists in control node, save request as RequestToJoinStateDeclined
|
alreadyProcessedByControlNode := existingRequestToJoin.State == RequestToJoinStateAccepted || existingRequestToJoin.State == RequestToJoinStateDeclined
|
||||||
// If request to join does not exist in control node, save request as RequestToJoinStateDeclinedPending
|
if alreadyProcessedByControlNode || existingRequestToJoin.State == RequestToJoinStateCanceled {
|
||||||
// as privileged users don't have revealed addresses. This can happen if control node received
|
continue
|
||||||
// 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
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requestUpdated, err := m.saveOrUpdateRequestToJoin(community.ID(), requestToJoin)
|
requestUpdated, err := m.saveOrUpdateRequestToJoin(community.ID(), requestToJoin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if community.IsControlNode() && requestUpdated {
|
||||||
rejectedRequestsToJoin = append(rejectedRequestsToJoin, requestToJoin.ID)
|
rejectedRequestsToJoin = append(rejectedRequestsToJoin, requestToJoin.ID)
|
||||||
}
|
}
|
||||||
|
@ -1788,9 +1778,9 @@ func (m *Manager) handleCommunityEventRequestRejected(community *Community, comm
|
||||||
return requestsToJoin, nil
|
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
|
// 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) {
|
if community.HasMember(pk) {
|
||||||
return m.persistence.SetRequestToJoinState(common.PubkeyToHex(pk), community.ID(), RequestToJoinStateAccepted)
|
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
|
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() {
|
if community.IsControlNode() {
|
||||||
revealedAccounts, err := m.persistence.GetRequestToJoinRevealedAddresses(dbRequest.ID)
|
revealedAccounts, err := m.persistence.GetRequestToJoinRevealedAddresses(dbRequest.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2021,17 +1983,10 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.markRequestToJoin(pk, community); err != nil {
|
if err := m.markRequestToJoinAsAccepted(pk, community); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
err = m.saveAndPublish(community)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if community.IsControlNode() {
|
|
||||||
if err = m.shareAcceptedRequestToJoinWithPrivilegedMembers(community, dbRequest); err != nil {
|
if err = m.shareAcceptedRequestToJoinWithPrivilegedMembers(community, dbRequest); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -2047,6 +2002,31 @@ func (m *Manager) AcceptRequestToJoin(dbRequest *RequestToJoin) (*Community, err
|
||||||
return nil, 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
|
return community, nil
|
||||||
|
@ -2062,16 +2042,17 @@ func (m *Manager) DeclineRequestToJoin(dbRequest *RequestToJoin) (*Community, er
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
requestToJoinState := RequestToJoinStateDeclined
|
adminEventCreated, err := community.DeclineRequestToJoin(dbRequest)
|
||||||
if community.HasPermissionToSendCommunityEvents() {
|
|
||||||
requestToJoinState = RequestToJoinStateDeclinedPending
|
|
||||||
}
|
|
||||||
err = m.persistence.SetRequestToJoinState(dbRequest.PublicKey, dbRequest.CommunityID, requestToJoinState)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// don't process request as admin if community is configured as auto-accept
|
||||||
if !community.IsControlNode() && community.AcceptRequestToJoinAutomatically() {
|
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
|
// control node must receive requests to join only on community address
|
||||||
|
@ -2188,93 +2169,69 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, receiver
|
||||||
return nil, err
|
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
|
// request to join was already processed by an admin and waits to get
|
||||||
// confirmation for its decision
|
// confirmation for its decision
|
||||||
//
|
//
|
||||||
// we're only interested in immediately declining any declined/pending
|
// we're only interested in immediately declining any declined/pending
|
||||||
// requests here, because if it's accepted/pending, we still need to perform
|
// requests here, because if it's accepted/pending, we still need to perform
|
||||||
// some checks
|
// some checks
|
||||||
if existingRequestToJoin.State == RequestToJoinStateDeclinedPending {
|
if existingRequestToJoin != nil && existingRequestToJoin.State == RequestToJoinStateDeclinedPending {
|
||||||
if community.IsControlNode() {
|
requestToJoin.State = RequestToJoinStateDeclined
|
||||||
requestToJoin.State = RequestToJoinStateDeclined
|
|
||||||
}
|
|
||||||
return requestToJoin, nil
|
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
|
// verify if revealed addresses indeed belong to requester
|
||||||
for _, revealedAccount := range request.RevealedAccounts {
|
for _, revealedAccount := range request.RevealedAccounts {
|
||||||
recoverParams := account.RecoverParams{
|
recoverParams := account.RecoverParams{
|
||||||
Message: types.EncodeHex(crypto.Keccak256(crypto.CompressPubkey(signer), community.ID(), requestToJoin.ID)),
|
Message: types.EncodeHex(crypto.Keccak256(crypto.CompressPubkey(signer), community.ID(), requestToJoin.ID)),
|
||||||
Signature: types.EncodeHex(revealedAccount.Signature),
|
Signature: types.EncodeHex(revealedAccount.Signature),
|
||||||
|
}
|
||||||
|
|
||||||
|
matching, err := m.accountsManager.CanRecover(recoverParams, types.HexToAddress(revealedAccount.Address))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !matching {
|
||||||
|
// if ownership of only one wallet address cannot be verified,
|
||||||
|
// we mark the request as cancelled and stop
|
||||||
|
requestToJoin.State = RequestToJoinStateDeclined
|
||||||
|
return requestToJoin, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matching, err := m.accountsManager.CanRecover(recoverParams, types.HexToAddress(revealedAccount.Address))
|
// Save revealed addresses + signatures so they can later be added
|
||||||
|
// to the control node's local table of known revealed addresses
|
||||||
|
err = m.persistence.SaveRequestToJoinRevealedAddresses(requestToJoin.ID, requestToJoin.RevealedAccounts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !matching {
|
|
||||||
// if ownership of only one wallet address cannot be verified,
|
|
||||||
// we mark the request as cancelled and stop
|
|
||||||
requestToJoin.State = RequestToJoinStateDeclined
|
|
||||||
return requestToJoin, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save revealed addresses + signatures so they can later be added
|
// If user is already a member, then accept request automatically
|
||||||
// to the control node's local table of known revealed addresses
|
// It may happen when member removes itself from community and then tries to rejoin
|
||||||
err = m.persistence.SaveRequestToJoinRevealedAddresses(requestToJoin.ID, requestToJoin.RevealedAccounts)
|
// More specifically, CommunityRequestToLeave may be delivered later than CommunityRequestToJoin, or not delivered at all
|
||||||
if err != nil {
|
acceptAutomatically := community.AcceptRequestToJoinAutomatically() || community.HasMember(signer)
|
||||||
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
|
||||||
|
acceptedByAdmin := existingRequestToJoin != nil && existingRequestToJoin.State == RequestToJoinStateAcceptedPending
|
||||||
// If user is already a member, then accept request automatically
|
if acceptAutomatically || acceptedByAdmin {
|
||||||
// It may happen when member removes itself from community and then tries to rejoin
|
err = m.markRequestToJoinAsAccepted(signer, community)
|
||||||
// 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 err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Don't check permissions here,
|
// Don't check permissions here,
|
||||||
// it will be done further in the processing pipeline.
|
// it will be done further in the processing pipeline.
|
||||||
requestToJoin.State = RequestToJoinStateAccepted
|
requestToJoin.State = RequestToJoinStateAccepted
|
||||||
} else {
|
return requestToJoin, nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2882,7 +2839,7 @@ func (m *Manager) HandleCommunityRequestToJoinResponse(signer *ecdsa.PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.Accepted {
|
if request.Accepted {
|
||||||
err = m.markRequestToJoin(&m.identity.PublicKey, community)
|
err = m.markRequestToJoinAsAccepted(&m.identity.PublicKey, community)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
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) {
|
func AddTimeoutToRequestToJoinClock(clock uint64) (uint64, error) {
|
||||||
requestToJoinClock, err := strconv.ParseInt(fmt.Sprint(clock), 10, 64)
|
requestToJoinClock, err := strconv.ParseInt(fmt.Sprint(clock), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -147,15 +147,6 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRejectMemberRequ
|
||||||
testRejectMemberRequestToJoin(s, community, user)
|
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() {
|
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
|
||||||
additionalOwner := s.newMessenger("", []string{})
|
additionalOwner := s.newMessenger("", []string{})
|
||||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
|
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
|
||||||
|
|
|
@ -168,15 +168,6 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJo
|
||||||
testRejectMemberRequestToJoin(s, community, user)
|
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() {
|
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
|
||||||
additionalTokenMaster := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
|
additionalTokenMaster := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
|
||||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
|
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
|
||||||
|
|
|
@ -1211,6 +1211,26 @@ func testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Len(acceptedPendingRequests, 1)
|
s.Require().Len(acceptedPendingRequests, 1)
|
||||||
s.Require().Equal(acceptedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
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) {
|
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().NoError(err)
|
||||||
s.Require().Len(rejectedPendingRequests, 1)
|
s.Require().Len(rejectedPendingRequests, 1)
|
||||||
s.Require().Equal(rejectedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
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) {
|
func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
|
||||||
|
@ -1367,78 +1408,6 @@ func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community
|
||||||
s.Require().Len(declinedRequestsPending, 0)
|
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) {
|
func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
||||||
_, err := user.Start()
|
_, err := user.Start()
|
||||||
|
|
||||||
|
|
|
@ -175,15 +175,6 @@ func (s *AdminCommunityEventsSuite) TestAdminRejectMemberRequestToJoin() {
|
||||||
testRejectMemberRequestToJoin(s, community, user)
|
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() {
|
func (s *AdminCommunityEventsSuite) TestAdminControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
|
||||||
additionalAdmin := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
|
additionalAdmin := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
|
||||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
|
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
|
||||||
|
@ -402,7 +393,7 @@ func (s *AdminCommunityEventsSuite) TestAdminDoesNotHaveRejectedEventsLoop() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// Update community clock without publishing new CommunityDescription
|
// Update community clock without publishing new CommunityDescription
|
||||||
err = community.DeclineRequestToJoin(nil)
|
_, err = community.DeclineRequestToJoin(nil)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
err = s.owner.communitiesManager.SaveCommunity(community)
|
err = s.owner.communitiesManager.SaveCommunity(community)
|
||||||
|
|
|
@ -1435,8 +1435,12 @@ func (m *Messenger) HandleCommunityRequestToJoin(state *ReceivedMessageState, re
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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{
|
accept := &requests.AcceptRequestToJoinCommunity{
|
||||||
ID: requestToJoin.ID,
|
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{
|
cancel := &requests.DeclineRequestToJoinCommunity{
|
||||||
ID: requestToJoin.ID,
|
ID: requestToJoin.ID,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue