MM-57873 Check user visibility when accepting channel invites for DMs (#27331)

* check user visibility when accepting channel invites for DMs

* stronger visibility checking for DM users

* check for correct remoteid for remote user in DM invite

* fix unit test

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Doug Lauder
2024-06-13 05:40:31 -04:00
коммит произвёл GitHub
родитель 9733694854
Коммит bf8ddb4bdc
5 изменённых файлов: 167 добавлений и 52 удалений

Просмотреть файл

@@ -4,6 +4,7 @@
package sharedchannel
import (
"context"
"encoding/json"
"errors"
"fmt"
@@ -24,6 +25,7 @@ var (
mockTypeChannel = mock.AnythingOfType("*model.Channel")
mockTypeString = mock.AnythingOfType("string")
mockTypeReqContext = mock.AnythingOfType("*request.Context")
mockTypeContext = mock.MatchedBy(func(ctx context.Context) bool { return true })
)
func TestOnReceiveChannelInvite(t *testing.T) {
@@ -157,48 +159,78 @@ func TestOnReceiveChannelInvite(t *testing.T) {
assert.Equal(t, fmt.Sprintf("cannot make channel readonly `%s`: foo: bar, boom", invitation.ChannelId), err.Error())
})
t.Run("when invitation prescribes a direct channel, it does create a direct channel", func(t *testing.T) {
mockServer := &MockServerIface{}
logger := mlog.CreateConsoleTestLogger(t)
mockServer.On("Log").Return(logger)
mockApp := &MockAppIface{}
scs := &Service{
server: mockServer,
app: mockApp,
t.Run("DM channels", func(t *testing.T) {
var testRemoteID = model.NewId()
testCases := []struct {
desc string
user1 *model.User
user2 *model.User
canSee bool
expectSuccess bool
}{
{"valid users", &model.User{Id: model.NewId(), RemoteId: &testRemoteID}, &model.User{Id: model.NewId()}, true, true},
{"swapped users", &model.User{Id: model.NewId()}, &model.User{Id: model.NewId(), RemoteId: &testRemoteID}, true, true},
{"two remotes", &model.User{Id: model.NewId(), RemoteId: &testRemoteID}, &model.User{Id: model.NewId(), RemoteId: &testRemoteID}, true, false},
{"two locals", &model.User{Id: model.NewId()}, &model.User{Id: model.NewId()}, true, false},
{"can't see", &model.User{Id: model.NewId(), RemoteId: &testRemoteID}, &model.User{Id: model.NewId()}, false, false},
{"invalid remoteid", &model.User{Id: model.NewId(), RemoteId: model.NewString("bogus")}, &model.User{Id: model.NewId()}, true, false},
}
mockStore := &mocks.Store{}
remoteCluster := &model.RemoteCluster{Name: "test3", CreatorId: model.NewId()}
invitation := channelInviteMsg{
ChannelId: model.NewId(),
TeamId: model.NewId(),
ReadOnly: false,
Type: model.ChannelTypeDirect,
DirectParticipantIDs: []string{model.NewId(), model.NewId()},
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
mockServer := &MockServerIface{}
logger := mlog.CreateConsoleTestLogger(t)
mockServer.On("Log").Return(logger)
mockApp := &MockAppIface{}
scs := &Service{
server: mockServer,
app: mockApp,
}
mockStore := &mocks.Store{}
remoteCluster := &model.RemoteCluster{Name: "test3", CreatorId: model.NewId(), RemoteId: testRemoteID}
invitation := channelInviteMsg{
ChannelId: model.NewId(),
TeamId: model.NewId(),
ReadOnly: false,
Type: model.ChannelTypeDirect,
DirectParticipantIDs: []string{tc.user1.Id, tc.user2.Id},
}
payload, err := json.Marshal(invitation)
require.NoError(t, err)
msg := model.RemoteClusterMsg{
Payload: payload,
}
mockChannelStore := mocks.ChannelStore{}
mockSharedChannelStore := mocks.SharedChannelStore{}
channel := &model.Channel{}
mockUserStore := mocks.UserStore{}
mockUserStore.On("Get", mockTypeContext, tc.user1.Id).
Return(tc.user1, nil)
mockUserStore.On("Get", mockTypeContext, tc.user2.Id).
Return(tc.user2, nil)
mockChannelStore.On("Get", invitation.ChannelId, true).Return(nil, errors.New("boom"))
mockSharedChannelStore.On("Save", mock.Anything).Return(nil, nil)
mockSharedChannelStore.On("SaveRemote", mock.Anything).Return(nil, nil)
mockStore.On("Channel").Return(&mockChannelStore)
mockStore.On("SharedChannel").Return(&mockSharedChannelStore)
mockStore.On("User").Return(&mockUserStore)
mockServer = scs.server.(*MockServerIface)
mockServer.On("GetStore").Return(mockStore)
mockApp.On("GetOrCreateDirectChannel", mockTypeReqContext, mockTypeString, mockTypeString, mock.AnythingOfType("model.ChannelOption")).
Return(channel, nil).Maybe()
mockApp.On("UserCanSeeOtherUser", mockTypeReqContext, mockTypeString, mockTypeString).Return(tc.canSee, nil).Maybe()
defer mockApp.AssertExpectations(t)
err = scs.onReceiveChannelInvite(msg, remoteCluster, nil)
require.Equal(t, tc.expectSuccess, err == nil)
})
}
payload, err := json.Marshal(invitation)
require.NoError(t, err)
msg := model.RemoteClusterMsg{
Payload: payload,
}
mockChannelStore := mocks.ChannelStore{}
mockSharedChannelStore := mocks.SharedChannelStore{}
channel := &model.Channel{}
mockChannelStore.On("Get", invitation.ChannelId, true).Return(nil, errors.New("boom"))
mockSharedChannelStore.On("Save", mock.Anything).Return(nil, nil)
mockSharedChannelStore.On("SaveRemote", mock.Anything).Return(nil, nil)
mockStore.On("Channel").Return(&mockChannelStore)
mockStore.On("SharedChannel").Return(&mockSharedChannelStore)
mockServer = scs.server.(*MockServerIface)
mockServer.On("GetStore").Return(mockStore)
mockApp.On("GetOrCreateDirectChannel", mock.AnythingOfType("*request.Context"), invitation.DirectParticipantIDs[0], invitation.DirectParticipantIDs[1], mock.AnythingOfType("model.ChannelOption")).Return(channel, nil)
defer mockApp.AssertExpectations(t)
err = scs.onReceiveChannelInvite(msg, remoteCluster, nil)
require.NoError(t, err)
})
}