MM-60240 Sanitize Channels based on user permissions (#28086)

* initial commit

* add unit tests

* update tests, self review

* update tests to verify something returned.

* update app-layer

* update unit tests

* fix tests

* add check for PermissionSysconsoleReadComplianceDataRetentionPolicy

* revert package-lock

* review suggestions

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Scott Bishel
2024-09-17 15:19:03 -06:00
коммит произвёл GitHub
родитель d99961f106
Коммит c12e6d9e9c
4 изменённых файлов: 147 добавлений и 2 удалений

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

@@ -793,8 +793,9 @@ func getPinnedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
func getAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
permissions := []*model.Permission{
model.PermissionSysconsoleReadUserManagementGroups,
model.PermissionSysconsoleWriteUserManagementGroups,
model.PermissionSysconsoleReadUserManagementChannels,
model.PermissionSysconsoleReadComplianceDataRetentionPolicy,
}
if !c.App.SessionHasPermissionToAny(*c.AppContext.Session(), permissions) {
c.SetPermissionError(permissions...)
@@ -822,6 +823,8 @@ func getAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
channels = sanitizeAllChannelsResponse(c, channels)
if c.Params.IncludeTotalCount {
totalCount, err := c.App.GetAllChannelsCount(c.AppContext, opts)
if err != nil {
@@ -843,6 +846,18 @@ func getAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
func sanitizeAllChannelsResponse(c *Context, channels model.ChannelListWithTeamData) model.ChannelListWithTeamData {
if !c.App.SessionHasPermissionToAny(*c.AppContext.Session(), []*model.Permission{
model.PermissionSysconsoleReadComplianceDataRetentionPolicy,
model.PermissionSysconsoleReadUserManagementChannels,
}) {
for _, channel := range channels {
channel.Channel = channel.Channel.Sanitize()
}
}
return channels
}
func getPublicChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamId()
if c.Err != nil {
@@ -1256,7 +1271,12 @@ func searchAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadUserManagementChannels) {
if !c.App.SessionHasPermissionToAny(*c.AppContext.Session(),
[]*model.Permission{
model.PermissionSysconsoleWriteUserManagementGroups,
model.PermissionSysconsoleReadUserManagementChannels,
model.PermissionSysconsoleReadComplianceDataRetentionPolicy,
}) {
c.SetPermissionError(model.PermissionSysconsoleReadUserManagementChannels)
return
}
@@ -1288,6 +1308,8 @@ func searchAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
channels = sanitizeAllChannelsResponse(c, channels)
// Don't fill in channels props, since unused by client and potentially expensive.
if props.Page != nil && props.PerPage != nil {
data := model.ChannelsWithCount{Channels: channels, TotalCount: totalCount}

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

@@ -1404,6 +1404,40 @@ func TestGetAllChannels(t *testing.T) {
}
require.True(t, found)
})
t.Run("verify correct sanitization", func(t *testing.T) {
channels, resp, err := th.SystemAdminClient.GetAllChannels(context.Background(), 0, 10000, "")
require.NoError(t, err)
CheckOKStatus(t, resp)
require.True(t, len(channels) > 0)
for _, channel := range channels {
if channel.DisplayName != "Off-Topic" && channel.DisplayName != "Town Square" {
require.NotEqual(t, "", channel.CreatorId)
require.NotEqual(t, "", channel.Name)
}
}
channels, resp, err = th.SystemManagerClient.GetAllChannels(context.Background(), 0, 10000, "")
require.NoError(t, err)
CheckOKStatus(t, resp)
require.True(t, len(channels) > 0)
for _, channel := range channels {
if channel.DisplayName != "Off-Topic" && channel.DisplayName != "Town Square" {
require.NotEqual(t, "", channel.CreatorId)
require.NotEqual(t, "", channel.Name)
}
}
th.RemovePermissionFromRole(model.PermissionSysconsoleReadUserManagementChannels.Id, model.SystemManagerRoleId)
channels, resp, err = th.SystemManagerClient.GetAllChannels(context.Background(), 0, 10000, "")
require.NoError(t, err)
CheckOKStatus(t, resp)
require.True(t, len(channels) > 0)
for _, channel := range channels {
require.Equal(t, "", channel.CreatorId)
require.Equal(t, "", channel.Name)
}
})
}
func TestGetAllChannelsWithCount(t *testing.T) {
@@ -1887,6 +1921,40 @@ func TestSearchAllChannels(t *testing.T) {
}
require.True(t, found)
})
t.Run("verify correct sanitization", func(t *testing.T) {
channels, resp, err := th.SystemAdminClient.SearchAllChannels(context.Background(), &model.ChannelSearch{Term: ""})
require.NoError(t, err)
CheckOKStatus(t, resp)
require.True(t, len(channels) > 0)
for _, channel := range channels {
if channel.DisplayName != "Off-Topic" && channel.DisplayName != "Town Square" {
require.NotEqual(t, "", channel.CreatorId)
require.NotEqual(t, "", channel.Name)
}
}
channels, resp, err = th.SystemManagerClient.SearchAllChannels(context.Background(), &model.ChannelSearch{Term: ""})
require.NoError(t, err)
CheckOKStatus(t, resp)
require.True(t, len(channels) > 0)
for _, channel := range channels {
if channel.DisplayName != "Off-Topic" && channel.DisplayName != "Town Square" {
require.NotEqual(t, "", channel.CreatorId)
require.NotEqual(t, "", channel.Name)
}
}
th.RemovePermissionFromRole(model.PermissionSysconsoleReadUserManagementChannels.Id, model.SystemManagerRoleId)
channels, resp, err = th.SystemManagerClient.SearchAllChannels(context.Background(), &model.ChannelSearch{Term: ""})
require.NoError(t, err)
require.True(t, len(channels) > 0)
CheckOKStatus(t, resp)
for _, channel := range channels {
require.Equal(t, "", channel.CreatorId)
require.Equal(t, "", channel.Name)
}
})
}
func TestSearchAllChannelsPaged(t *testing.T) {