Fixing permissions checks where related to join public channels (#10511)
* Fixing permissions checks where related to join public channels * Addressing PR review comments * Fixing bug * Adding new tests * Addressing PR review comments
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
9b73d34eaa
Коммит
9fa6b093f3
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mattermost/mattermost-server/mlog"
|
"github.com/mattermost/mattermost-server/mlog"
|
||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
|
"github.com/mattermost/mattermost-server/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (api *API) InitChannel() {
|
func (api *API) InitChannel() {
|
||||||
@@ -411,7 +412,7 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if channel.Type == model.CHANNEL_OPEN {
|
if channel.Type == model.CHANNEL_OPEN {
|
||||||
if !c.App.SessionHasPermissionToTeam(c.App.Session, channel.TeamId, model.PERMISSION_READ_PUBLIC_CHANNEL) {
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, channel.TeamId, model.PERMISSION_READ_PUBLIC_CHANNEL) && !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
||||||
c.SetPermissionError(model.PERMISSION_READ_PUBLIC_CHANNEL)
|
c.SetPermissionError(model.PERMISSION_READ_PUBLIC_CHANNEL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -800,7 +801,7 @@ func getChannelByName(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if channel.Type == model.CHANNEL_OPEN {
|
if channel.Type == model.CHANNEL_OPEN {
|
||||||
if !c.App.SessionHasPermissionToTeam(c.App.Session, channel.TeamId, model.PERMISSION_READ_PUBLIC_CHANNEL) {
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, channel.TeamId, model.PERMISSION_READ_PUBLIC_CHANNEL) && !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_READ_CHANNEL) {
|
||||||
c.SetPermissionError(model.PERMISSION_READ_PUBLIC_CHANNEL)
|
c.SetPermissionError(model.PERMISSION_READ_PUBLIC_CHANNEL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1124,14 +1125,32 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check join permission if adding yourself, otherwise check manage permission
|
if channel.Type == model.CHANNEL_DIRECT || channel.Type == model.CHANNEL_GROUP {
|
||||||
|
c.Err = model.NewAppError("addUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isNewMembership := false
|
||||||
|
if _, err = c.App.GetChannelMember(member.ChannelId, member.UserId); err != nil {
|
||||||
|
if err.Id == store.MISSING_CHANNEL_MEMBER_ERROR {
|
||||||
|
isNewMembership = true
|
||||||
|
} else {
|
||||||
|
c.Err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelfAdd := member.UserId == c.App.Session.UserId
|
||||||
|
|
||||||
if channel.Type == model.CHANNEL_OPEN {
|
if channel.Type == model.CHANNEL_OPEN {
|
||||||
if member.UserId == c.App.Session.UserId {
|
if isSelfAdd && isNewMembership {
|
||||||
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_JOIN_PUBLIC_CHANNELS) {
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, channel.TeamId, model.PERMISSION_JOIN_PUBLIC_CHANNELS) {
|
||||||
c.SetPermissionError(model.PERMISSION_JOIN_PUBLIC_CHANNELS)
|
c.SetPermissionError(model.PERMISSION_JOIN_PUBLIC_CHANNELS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else if isSelfAdd && !isNewMembership {
|
||||||
|
// nothing to do, since already in the channel
|
||||||
|
} else if !isSelfAdd {
|
||||||
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
|
||||||
c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS)
|
c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS)
|
||||||
return
|
return
|
||||||
@@ -1139,15 +1158,21 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.Type == model.CHANNEL_PRIVATE && !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
|
if channel.Type == model.CHANNEL_PRIVATE {
|
||||||
|
if isSelfAdd && isNewMembership {
|
||||||
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
|
||||||
c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS)
|
c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if isSelfAdd && !isNewMembership {
|
||||||
if channel.Type == model.CHANNEL_DIRECT || channel.Type == model.CHANNEL_GROUP {
|
// nothing to do, since already in the channel
|
||||||
c.Err = model.NewAppError("addUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest)
|
} else if !isSelfAdd {
|
||||||
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
|
||||||
|
c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cm, err := c.App.AddChannelMember(member.UserId, channel, c.App.Session.UserId, postRootId, c.App.Session.Id)
|
cm, err := c.App.AddChannelMember(member.UserId, channel, c.App.Session.UserId, postRootId, c.App.Session.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -2023,6 +2023,82 @@ func TestAddChannelMember(t *testing.T) {
|
|||||||
Client.Logout()
|
Client.Logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddChannelMemberAddMyself(t *testing.T) {
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
Client := th.Client
|
||||||
|
user := th.CreateUser()
|
||||||
|
th.LinkUserToTeam(user, th.BasicTeam)
|
||||||
|
notMemberPublicChannel1 := th.CreatePublicChannel()
|
||||||
|
notMemberPublicChannel2 := th.CreatePublicChannel()
|
||||||
|
notMemberPrivateChannel := th.CreatePrivateChannel()
|
||||||
|
|
||||||
|
memberPublicChannel := th.CreatePublicChannel()
|
||||||
|
memberPrivateChannel := th.CreatePrivateChannel()
|
||||||
|
th.AddUserToChannel(user, memberPublicChannel)
|
||||||
|
th.AddUserToChannel(user, memberPrivateChannel)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
Channel *model.Channel
|
||||||
|
WithJoinPublicPermission bool
|
||||||
|
ExpectedError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Add myself to a public channel with JOIN_PUBLIC_CHANNEL permission",
|
||||||
|
notMemberPublicChannel1,
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Try to add myself to a private channel with the JOIN_PUBLIC_CHANNEL permission",
|
||||||
|
notMemberPrivateChannel,
|
||||||
|
true,
|
||||||
|
"api.context.permissions.app_error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Try to add myself to a public channel without the JOIN_PUBLIC_CHANNEL permission",
|
||||||
|
notMemberPublicChannel2,
|
||||||
|
false,
|
||||||
|
"api.context.permissions.app_error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Add myself a public channel where I'm already a member, not having JOIN_PUBLIC_CHANNEL or MANAGE MEMBERS permission",
|
||||||
|
memberPublicChannel,
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Add myself a private channel where I'm already a member, not having JOIN_PUBLIC_CHANNEL or MANAGE MEMBERS permission",
|
||||||
|
memberPrivateChannel,
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Client.Login(user.Email, user.Password)
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
|
|
||||||
|
// Check the appropriate permissions are enforced.
|
||||||
|
defaultRolePermissions := th.SaveDefaultRolePermissions()
|
||||||
|
defer func() {
|
||||||
|
th.RestoreDefaultRolePermissions(defaultRolePermissions)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if !tc.WithJoinPublicPermission {
|
||||||
|
th.RemovePermissionFromRole(model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id, model.TEAM_USER_ROLE_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp := Client.AddChannelMember(tc.Channel.Id, user.Id)
|
||||||
|
if tc.ExpectedError == "" {
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
} else {
|
||||||
|
CheckErrorMessage(t, resp, tc.ExpectedError)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRemoveChannelMember(t *testing.T) {
|
func TestRemoveChannelMember(t *testing.T) {
|
||||||
th := Setup().InitBasic()
|
th := Setup().InitBasic()
|
||||||
user1 := th.BasicUser
|
user1 := th.BasicUser
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user