MM-49813 - validate inviter permissions when sending invitations to private channels (#22119)
* MM-49813 - validate members invitation permissions to private channels * Validate on the receiver side that the sender id still has permissions to invite * add translations * fix texts * simplify implementation * remove local test hardcoded data * add test to user_test * fix vet warning * Add comments to validate user permissions function Co-authored-by: Martin Kraft <martin@upspin.org> * regenerate app layer iface * fix unit test * fix app user_tests --------- Co-authored-by: Martin Kraft <martin@upspin.org>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e055df27e8
Коммит
ae3c21dd79
@@ -1405,6 +1405,9 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
auditRec.AddMeta("emails", emailList)
|
||||
|
||||
if len(memberInvite.ChannelIds) > 0 {
|
||||
// Check if the user sending the invitation has access to the channels where the invitation is being sent
|
||||
memberInvite.ChannelIds = c.App.ValidateUserPermissionsOnChannels(c.AppContext, c.AppContext.Session().UserId, memberInvite.ChannelIds)
|
||||
|
||||
auditRec.AddMeta("channel_count", len(memberInvite.ChannelIds))
|
||||
auditRec.AddMeta("channels", memberInvite.ChannelIds)
|
||||
}
|
||||
@@ -1521,6 +1524,9 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request)
|
||||
auditRec.AddMeta("channel_count", len(guestsInvite.Channels))
|
||||
auditRec.AddMeta("channels", guestsInvite.Channels)
|
||||
|
||||
// Check if the user sending the invitation has access to the channels where the invitation is being sent
|
||||
guestsInvite.Channels = c.App.ValidateUserPermissionsOnChannels(c.AppContext, c.AppContext.Session().UserId, guestsInvite.Channels)
|
||||
|
||||
if graceful {
|
||||
var invitesWithError []*model.EmailInviteWithError
|
||||
var appErr *model.AppError
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package api4
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/app"
|
||||
"github.com/mattermost/mattermost-server/v6/app/request"
|
||||
"github.com/mattermost/mattermost-server/v6/einterfaces/mocks"
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/plugin/plugintest/mock"
|
||||
@@ -3157,6 +3159,37 @@ func TestImportTeam(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateUserPermissionsOnChannels(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
// define user session and context
|
||||
context := request.NewContext(context.Background(), model.NewId(), model.NewId(), model.NewId(), model.NewId(), model.NewId(), model.Session{}, nil)
|
||||
|
||||
t.Run("User WITH permissions on private channel CAN invite members to it", func(t *testing.T) {
|
||||
channelIds := []string{th.BasicChannel.Id, th.BasicPrivateChannel.Id}
|
||||
|
||||
require.Len(t, channelIds, 2)
|
||||
|
||||
channelIds = th.App.ValidateUserPermissionsOnChannels(context, th.BasicUser.Id, channelIds)
|
||||
|
||||
// basicUser has permission onBasicChannel and BasicPrivateChannel so he can invite to both channels
|
||||
require.Len(t, channelIds, 2)
|
||||
})
|
||||
|
||||
t.Run("User WITHOUT permissions on private channel CAN NOT invite members to it", func(t *testing.T) {
|
||||
channelIdWithoutPermissions := th.BasicPrivateChannel2.Id
|
||||
channelIds := []string{th.BasicChannel.Id, channelIdWithoutPermissions}
|
||||
|
||||
require.Len(t, channelIds, 2)
|
||||
|
||||
channelIds = th.App.ValidateUserPermissionsOnChannels(context, th.BasicUser.Id, channelIds)
|
||||
|
||||
// basicUser DOES NOT have permission on BasicPrivateChannel2 so he can only invite to BasicChannel
|
||||
require.Len(t, channelIds, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInviteUsersToTeam(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
@@ -382,6 +382,44 @@ func TestCreateUserWithToken(t *testing.T) {
|
||||
_, err = th.App.Srv().Store().Token().GetByToken(token.Token)
|
||||
require.Error(t, err, "The token must be deleted after be used")
|
||||
})
|
||||
|
||||
t.Run("Validate inviter user has permissions on channels he is inviting", func(t *testing.T) {
|
||||
user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SystemUserRoleId}
|
||||
channelIdWithoutPermissions := th.BasicPrivateChannel2.Id
|
||||
channelIds := th.BasicChannel.Id + " " + channelIdWithoutPermissions
|
||||
token := model.NewToken(
|
||||
app.TokenTypeTeamInvitation,
|
||||
model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email, "senderId": th.BasicUser.Id, "channels": channelIds}),
|
||||
)
|
||||
require.NoError(t, th.App.Srv().Store().Token().Save(token))
|
||||
|
||||
ruser, resp, err := th.Client.CreateUserWithToken(&user, token.Token)
|
||||
require.NoError(t, err)
|
||||
CheckCreatedStatus(t, resp)
|
||||
|
||||
th.Client.Login(user.Email, user.Password)
|
||||
require.Equal(t, user.Nickname, ruser.Nickname)
|
||||
require.Equal(t, model.SystemUserRoleId, ruser.Roles, "should clear roles")
|
||||
CheckUserSanitization(t, ruser)
|
||||
_, err = th.App.Srv().Store().Token().GetByToken(token.Token)
|
||||
require.Error(t, err, "The token must be deleted after being used")
|
||||
|
||||
teams, appErr := th.App.GetTeamsForUser(ruser.Id)
|
||||
require.Nil(t, appErr)
|
||||
require.NotEmpty(t, teams, "The user must have teams")
|
||||
require.Equal(t, th.BasicTeam.Id, teams[0].Id, "The user joined team must be the team provided.")
|
||||
|
||||
// Now we get all the channels for the just created user
|
||||
channelList, cErr := th.App.GetChannelsForTeamForUser(th.Context, th.BasicTeam.Id, ruser.Id, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
require.Nil(t, cErr)
|
||||
|
||||
// basicUser has no permissions on BasicPrivateChannel2 so the new invited user should be able to only access
|
||||
// one channel from the two he was invited (plus the two default channels)
|
||||
require.Len(t, channelList, 3)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateUserWebSocketEvent(t *testing.T) {
|
||||
|
||||
Ссылка в новой задаче
Block a user