Community member joins the community if he sends a request to join an… (#4321)
This commit is contained in:
parent
71b27394bb
commit
be8568e174
|
@ -66,6 +66,7 @@ func SetValidateInterval(duration time.Duration) {
|
|||
var (
|
||||
ErrTorrentTimedout = errors.New("torrent has timed out")
|
||||
ErrCommunityRequestAlreadyRejected = errors.New("that user was already rejected from the community")
|
||||
ErrInvalidClock = errors.New("invalid clock to cancel request to join")
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
|
@ -2326,6 +2327,15 @@ func (m *Manager) HandleCommunityCancelRequestToJoin(signer *ecdsa.PublicKey, re
|
|||
return nil, ErrOrgNotFound
|
||||
}
|
||||
|
||||
previousRequestToJoin, err := m.GetRequestToJoinByPkAndCommunityID(signer, community.ID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if request.Clock <= previousRequestToJoin.Clock {
|
||||
return nil, ErrInvalidClock
|
||||
}
|
||||
|
||||
retainDeclined, err := m.shouldUserRetainDeclined(signer, community, request.Clock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -2344,6 +2354,18 @@ func (m *Manager) HandleCommunityCancelRequestToJoin(signer *ecdsa.PublicKey, re
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if community.HasMember(signer) {
|
||||
_, err = community.RemoveUserFromOrg(signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = m.saveAndPublish(community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return requestToJoin, nil
|
||||
}
|
||||
|
||||
|
@ -2922,6 +2944,10 @@ func (m *Manager) GetCommunityRequestToJoinClock(pk *ecdsa.PublicKey, communityI
|
|||
return request.Clock, nil
|
||||
}
|
||||
|
||||
func (m *Manager) GetRequestToJoinByPkAndCommunityID(pk *ecdsa.PublicKey, communityID []byte) (*RequestToJoin, error) {
|
||||
return m.persistence.GetRequestToJoinByPkAndCommunityID(common.PubkeyToHex(pk), communityID)
|
||||
}
|
||||
|
||||
func (m *Manager) UpdateCommunityDescriptionMagnetlinkMessageClock(communityID types.HexBytes, clock uint64) error {
|
||||
community, err := m.GetByIDString(communityID.String())
|
||||
if err != nil {
|
||||
|
@ -3272,6 +3298,10 @@ func (m *Manager) CanceledRequestsToJoinForUser(pk *ecdsa.PublicKey) ([]*Request
|
|||
return m.persistence.CanceledRequestsToJoinForUser(common.PubkeyToHex(pk))
|
||||
}
|
||||
|
||||
func (m *Manager) CanceledRequestToJoinForUserForCommunityID(pk *ecdsa.PublicKey, communityID []byte) (*RequestToJoin, error) {
|
||||
return m.persistence.CanceledRequestToJoinForUserForCommunityID(common.PubkeyToHex(pk), communityID)
|
||||
}
|
||||
|
||||
func (m *Manager) PendingRequestsToJoin() ([]*RequestToJoin, error) {
|
||||
return m.persistence.PendingRequestsToJoin()
|
||||
}
|
||||
|
|
|
@ -688,6 +688,26 @@ func (p *Persistence) CanceledRequestsToJoinForUser(pk string) ([]*RequestToJoin
|
|||
return requests, nil
|
||||
}
|
||||
|
||||
func (p *Persistence) CanceledRequestToJoinForUserForCommunityID(pk string, communityID []byte) (*RequestToJoin, error) {
|
||||
row := p.db.QueryRow(`SELECT id,public_key,clock,ens_name,chat_id,community_id,state
|
||||
FROM
|
||||
communities_requests_to_join
|
||||
WHERE
|
||||
state = ? AND public_key = ? AND community_id = ?`,
|
||||
RequestToJoinStateCanceled, pk, communityID)
|
||||
|
||||
request := &RequestToJoin{}
|
||||
|
||||
err := row.Scan(&request.ID, &request.PublicKey, &request.Clock, &request.ENSName, &request.ChatID, &request.CommunityID, &request.State)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (p *Persistence) RequestsToJoinForUserByState(pk string, state RequestToJoinState) ([]*RequestToJoin, error) {
|
||||
var requests []*RequestToJoin
|
||||
rows, err := p.db.Query(`SELECT id,public_key,clock,ens_name,chat_id,community_id,state FROM communities_requests_to_join WHERE state = ? AND public_key = ?`, state, pk)
|
||||
|
|
|
@ -3774,3 +3774,164 @@ func (s *MessengerCommunitiesSuite) TestRetrieveBigCommunity() {
|
|||
}, "updated description not received")
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *MessengerCommunitiesSuite) TestRequestAndCancelCommunityAdminOffline() {
|
||||
ctx := context.Background()
|
||||
|
||||
community, _ := s.createCommunity()
|
||||
s.advertiseCommunityTo(community, s.owner, s.alice)
|
||||
|
||||
request := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
||||
// We try to join the org
|
||||
response, err := s.alice.RequestToJoinCommunity(request)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
||||
|
||||
requestToJoin1 := response.RequestsToJoinCommunity[0]
|
||||
s.Require().NotNil(requestToJoin1)
|
||||
s.Require().Equal(community.ID(), requestToJoin1.CommunityID)
|
||||
s.Require().True(requestToJoin1.Our)
|
||||
s.Require().NotEmpty(requestToJoin1.ID)
|
||||
s.Require().NotEmpty(requestToJoin1.Clock)
|
||||
s.Require().Equal(requestToJoin1.PublicKey, common.PubkeyToHex(&s.alice.identity.PublicKey))
|
||||
s.Require().Equal(communities.RequestToJoinStatePending, requestToJoin1.State)
|
||||
|
||||
messageState := s.alice.buildMessageState()
|
||||
messageState.CurrentMessageState = &CurrentMessageState{}
|
||||
|
||||
messageState.CurrentMessageState.PublicKey = &s.alice.identity.PublicKey
|
||||
|
||||
statusMessage := v1protocol.StatusMessage{}
|
||||
statusMessage.TransportLayer.Dst = community.PublicKey()
|
||||
|
||||
requestToJoinProto := &protobuf.CommunityRequestToJoin{
|
||||
Clock: requestToJoin1.Clock,
|
||||
EnsName: requestToJoin1.ENSName,
|
||||
DisplayName: "Alice",
|
||||
CommunityId: community.ID(),
|
||||
}
|
||||
|
||||
err = s.owner.HandleCommunityRequestToJoin(messageState, requestToJoinProto, &statusMessage)
|
||||
s.Require().NoError(err)
|
||||
ownerCommunity, err := s.owner.GetCommunityByID(community.ID())
|
||||
// Check Alice has successfully joined at owner side, Because message order was correct
|
||||
s.Require().True(ownerCommunity.HasMember(s.alice.IdentityPublicKey()))
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Len(response.Communities(), 1)
|
||||
s.Require().Equal(response.Communities()[0].RequestedToJoinAt(), requestToJoin1.Clock)
|
||||
|
||||
// pull all communities to make sure we set RequestedToJoinAt
|
||||
|
||||
allCommunities, err := s.alice.Communities()
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(allCommunities, 2)
|
||||
|
||||
if bytes.Equal(allCommunities[0].ID(), community.ID()) {
|
||||
s.Require().Equal(allCommunities[0].RequestedToJoinAt(), requestToJoin1.Clock)
|
||||
} else {
|
||||
s.Require().Equal(allCommunities[1].RequestedToJoinAt(), requestToJoin1.Clock)
|
||||
}
|
||||
|
||||
// pull to make sure it has been saved
|
||||
requestsToJoin, err := s.alice.MyPendingRequestsToJoin()
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(requestsToJoin, 1)
|
||||
|
||||
// Make sure the requests are fetched also by community
|
||||
requestsToJoin, err = s.alice.PendingRequestsToJoinForCommunity(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(requestsToJoin, 1)
|
||||
|
||||
requestToJoin2 := response.RequestsToJoinCommunity[0]
|
||||
|
||||
s.Require().NotNil(requestToJoin2)
|
||||
s.Require().Equal(community.ID(), requestToJoin2.CommunityID)
|
||||
s.Require().NotEmpty(requestToJoin2.ID)
|
||||
s.Require().NotEmpty(requestToJoin2.Clock)
|
||||
s.Require().Equal(requestToJoin2.PublicKey, common.PubkeyToHex(&s.alice.identity.PublicKey))
|
||||
s.Require().Equal(communities.RequestToJoinStatePending, requestToJoin2.State)
|
||||
|
||||
s.Require().Equal(requestToJoin1.ID, requestToJoin2.ID)
|
||||
|
||||
requestToCancel := &requests.CancelRequestToJoinCommunity{ID: requestToJoin1.ID}
|
||||
response, err = s.alice.CancelRequestToJoinCommunity(ctx, requestToCancel)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
||||
s.Require().Equal(communities.RequestToJoinStateCanceled, response.RequestsToJoinCommunity[0].State)
|
||||
|
||||
messageState = s.alice.buildMessageState()
|
||||
messageState.CurrentMessageState = &CurrentMessageState{}
|
||||
|
||||
messageState.CurrentMessageState.PublicKey = &s.alice.identity.PublicKey
|
||||
|
||||
statusMessage.TransportLayer.Dst = community.PublicKey()
|
||||
|
||||
requestToJoinCancelProto := &protobuf.CommunityRequestToJoinResponse{
|
||||
CommunityId: community.ID(),
|
||||
Clock: requestToJoin1.Clock + 1,
|
||||
Accepted: true,
|
||||
}
|
||||
|
||||
err = s.alice.HandleCommunityRequestToJoinResponse(messageState, requestToJoinCancelProto, &statusMessage)
|
||||
s.Require().NoError(err)
|
||||
aliceJoinedCommunities, err := s.alice.JoinedCommunities()
|
||||
s.Require().NoError(err)
|
||||
// Make sure on Alice side she hasn't joined any communities
|
||||
s.Require().Empty(aliceJoinedCommunities)
|
||||
|
||||
// pull to make sure it has been saved
|
||||
cancelRequestsToJoin, err := s.alice.MyCanceledRequestToJoinForCommunityID(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(cancelRequestsToJoin)
|
||||
s.Require().Equal(cancelRequestsToJoin.State, communities.RequestToJoinStateCanceled)
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
messageState = s.alice.buildMessageState()
|
||||
messageState.CurrentMessageState = &CurrentMessageState{}
|
||||
|
||||
messageState.CurrentMessageState.PublicKey = &s.alice.identity.PublicKey
|
||||
|
||||
statusMessage.TransportLayer.Dst = community.PublicKey()
|
||||
|
||||
requestToJoinResponseProto := &protobuf.CommunityRequestToJoinResponse{
|
||||
Clock: cancelRequestsToJoin.Clock,
|
||||
CommunityId: community.ID(),
|
||||
Accepted: true,
|
||||
}
|
||||
|
||||
err = s.alice.HandleCommunityRequestToJoinResponse(messageState, requestToJoinResponseProto, &statusMessage)
|
||||
s.Require().NoError(err)
|
||||
// Make sure alice is NOT a member of the community that she cancelled her request to join to
|
||||
s.Require().False(community.HasMember(s.alice.IdentityPublicKey()))
|
||||
// Make sure there are no AC notifications for Alice
|
||||
aliceNotifications, err := s.alice.ActivityCenterNotifications(ActivityCenterNotificationsRequest{
|
||||
Cursor: "",
|
||||
Limit: 10,
|
||||
ActivityTypes: []ActivityCenterType{},
|
||||
ReadType: ActivityCenterQueryParamsReadUnread,
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(aliceNotifications.Notifications, 0)
|
||||
|
||||
// Retrieve activity center notifications for admin to make sure the request notification is deleted
|
||||
notifications, err := s.owner.ActivityCenterNotifications(ActivityCenterNotificationsRequest{
|
||||
Cursor: "",
|
||||
Limit: 10,
|
||||
ActivityTypes: []ActivityCenterType{},
|
||||
ReadType: ActivityCenterQueryParamsReadUnread,
|
||||
})
|
||||
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(notifications.Notifications, 0)
|
||||
cancelRequestToJoin2 := response.RequestsToJoinCommunity[0]
|
||||
s.Require().NotNil(cancelRequestToJoin2)
|
||||
s.Require().Equal(community.ID(), cancelRequestToJoin2.CommunityID)
|
||||
s.Require().False(cancelRequestToJoin2.Our)
|
||||
s.Require().NotEmpty(cancelRequestToJoin2.ID)
|
||||
s.Require().NotEmpty(cancelRequestToJoin2.Clock)
|
||||
s.Require().Equal(cancelRequestToJoin2.PublicKey, common.PubkeyToHex(&s.alice.identity.PublicKey))
|
||||
}
|
||||
|
|
|
@ -2355,6 +2355,10 @@ func (m *Messenger) MyCanceledRequestsToJoin() ([]*communities.RequestToJoin, er
|
|||
return m.communitiesManager.CanceledRequestsToJoinForUser(&m.identity.PublicKey)
|
||||
}
|
||||
|
||||
func (m *Messenger) MyCanceledRequestToJoinForCommunityID(communityID []byte) (*communities.RequestToJoin, error) {
|
||||
return m.communitiesManager.CanceledRequestToJoinForUserForCommunityID(&m.identity.PublicKey, communityID)
|
||||
}
|
||||
|
||||
func (m *Messenger) MyPendingRequestsToJoin() ([]*communities.RequestToJoin, error) {
|
||||
return m.communitiesManager.PendingRequestsToJoinForUser(&m.identity.PublicKey)
|
||||
}
|
||||
|
|
|
@ -1596,6 +1596,16 @@ func (m *Messenger) HandleCommunityRequestToJoinResponse(state *ReceivedMessageS
|
|||
return ErrInvalidCommunityID
|
||||
}
|
||||
|
||||
myCancelledRequestToJoin, err := m.MyCanceledRequestToJoinForCommunityID(requestToJoinResponseProto.CommunityId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if myCancelledRequestToJoin != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
updatedRequest, err := m.communitiesManager.HandleCommunityRequestToJoinResponse(signer, requestToJoinResponseProto)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1683,7 +1693,7 @@ func (m *Messenger) HandleCommunityRequestToJoinResponse(state *ReceivedMessageS
|
|||
notification.UpdatedAt = m.GetCurrentTimeInMillis()
|
||||
err = m.addActivityCenterNotification(state.Response, notification, nil)
|
||||
if err != nil {
|
||||
m.logger.Warn("failed to update notification", zap.Error(err))
|
||||
m.logger.Error("failed to update notification", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue