Automatic Merge
Этот коммит содержится в:
David Krauser
2026-05-04 03:17:40 -04:00
коммит произвёл GitHub
родитель 073bd3a6b7
Коммит 9408b98025
22 изменённых файлов: 562 добавлений и 69 удалений

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

@@ -6,6 +6,7 @@ package app
import (
"context"
"encoding/csv"
"errors"
"io"
"os"
"slices"
@@ -13,9 +14,11 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/v8/channels/store/storetest/mocks"
)
type permissionInheritanceTestData struct {
@@ -261,3 +264,225 @@ func testPermissionInheritance(t *testing.T, testCallback func(t *testing.T, th
// test 24 combinations where the higher-scoped scheme is a TEAM scheme
test(teamScheme.DefaultChannelGuestRole, teamScheme.DefaultChannelUserRole, teamScheme.DefaultChannelAdminRole)
}
func TestSendUpdatedRoleEvent(t *testing.T) {
t.Run("BuiltIn role broadcasts globally without a DB lookup", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockStore.On("Scheme").Return(&mockSchemeStore)
role := &model.Role{Name: model.TeamAdminRoleId, BuiltIn: true}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
mockSchemeStore.AssertNotCalled(t, "Get", mock.Anything)
})
t.Run("Team scheme role calls GetTeamsByScheme and emits per-team events", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
roleName := model.NewId()
scheme := &model.Scheme{Id: schemeID, Scope: model.SchemeScopeTeam}
teams := []*model.Team{{Id: model.NewId()}, {Id: model.NewId()}}
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockTeamStore := mocks.TeamStore{}
mockSchemeStore.On("Get", schemeID).Return(scheme, nil)
mockTeamStore.On("GetTeamsByScheme", schemeID, 0, 1000).Return(teams, nil)
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Team").Return(&mockTeamStore)
role := &model.Role{Name: roleName, BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
mockSchemeStore.AssertCalled(t, "Get", schemeID)
mockTeamStore.AssertCalled(t, "GetTeamsByScheme", schemeID, 0, 1000)
})
t.Run("Channel scheme role calls GetChannelsByScheme and emits per-channel events", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
roleName := model.NewId()
scheme := &model.Scheme{Id: schemeID, Scope: model.SchemeScopeChannel}
channels := model.ChannelList{{Id: model.NewId()}}
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockChannelStore := mocks.ChannelStore{}
mockSchemeStore.On("Get", schemeID).Return(scheme, nil)
mockChannelStore.On("GetChannelsByScheme", schemeID, 0, 1000).Return(channels, nil)
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Channel").Return(&mockChannelStore)
role := &model.Role{Name: roleName, BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
mockSchemeStore.AssertCalled(t, "Get", schemeID)
mockChannelStore.AssertCalled(t, "GetChannelsByScheme", schemeID, 0, 1000)
})
t.Run("Role not in any scheme broadcasts globally", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockTeamStore := mocks.TeamStore{}
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Team").Return(&mockTeamStore)
role := &model.Role{Name: model.NewId(), BuiltIn: false, SchemeId: nil}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
mockSchemeStore.AssertNotCalled(t, "Get", mock.Anything)
mockTeamStore.AssertNotCalled(t, "GetTeamsByScheme", mock.Anything, mock.Anything, mock.Anything)
})
t.Run("Playbook scope falls back to global broadcast without querying teams or channels", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
roleName := model.NewId()
scheme := &model.Scheme{Id: schemeID, Scope: model.SchemeScopePlaybook}
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockTeamStore := mocks.TeamStore{}
mockChannelStore := mocks.ChannelStore{}
mockSchemeStore.On("Get", schemeID).Return(scheme, nil)
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Team").Return(&mockTeamStore)
mockStore.On("Channel").Return(&mockChannelStore)
role := &model.Role{Name: roleName, BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
mockTeamStore.AssertNotCalled(t, "GetTeamsByScheme", mock.Anything, mock.Anything, mock.Anything)
mockChannelStore.AssertNotCalled(t, "GetChannelsByScheme", mock.Anything, mock.Anything, mock.Anything)
})
t.Run("Scheme store error is logged and skips broadcast", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
roleName := model.NewId()
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockSchemeStore.On("Get", schemeID).Return(nil, errors.New("db error"))
mockStore.On("Scheme").Return(&mockSchemeStore)
role := &model.Role{Name: roleName, BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
})
t.Run("GetTeamsByScheme store error propagates as AppError", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
roleName := model.NewId()
scheme := &model.Scheme{Id: schemeID, Scope: model.SchemeScopeTeam}
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockTeamStore := mocks.TeamStore{}
mockSchemeStore.On("Get", schemeID).Return(scheme, nil)
mockTeamStore.On("GetTeamsByScheme", schemeID, 0, 1000).Return(nil, errors.New("db error"))
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Team").Return(&mockTeamStore)
role := &model.Role{Name: roleName, BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.NotNil(t, appErr)
})
t.Run("Team scheme paginates across multiple pages", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
scheme := &model.Scheme{Id: schemeID, Scope: model.SchemeScopeTeam}
// Build a full first page (1000 teams) and a partial second page (2 teams).
page1 := make([]*model.Team, 1000)
for i := range page1 {
page1[i] = &model.Team{Id: model.NewId()}
}
page2 := []*model.Team{{Id: model.NewId()}, {Id: model.NewId()}}
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockTeamStore := mocks.TeamStore{}
mockSchemeStore.On("Get", schemeID).Return(scheme, nil)
mockTeamStore.On("GetTeamsByScheme", schemeID, 0, 1000).Return(page1, nil)
mockTeamStore.On("GetTeamsByScheme", schemeID, 1000, 1000).Return(page2, nil)
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Team").Return(&mockTeamStore)
role := &model.Role{Name: model.NewId(), BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
mockTeamStore.AssertCalled(t, "GetTeamsByScheme", schemeID, 0, 1000)
mockTeamStore.AssertCalled(t, "GetTeamsByScheme", schemeID, 1000, 1000)
})
t.Run("Channel scheme paginates across multiple pages", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
scheme := &model.Scheme{Id: schemeID, Scope: model.SchemeScopeChannel}
page1 := make(model.ChannelList, 1000)
for i := range page1 {
page1[i] = &model.Channel{Id: model.NewId()}
}
page2 := model.ChannelList{{Id: model.NewId()}, {Id: model.NewId()}, {Id: model.NewId()}}
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockChannelStore := mocks.ChannelStore{}
mockSchemeStore.On("Get", schemeID).Return(scheme, nil)
mockChannelStore.On("GetChannelsByScheme", schemeID, 0, 1000).Return(page1, nil)
mockChannelStore.On("GetChannelsByScheme", schemeID, 1000, 1000).Return(page2, nil)
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Channel").Return(&mockChannelStore)
role := &model.Role{Name: model.NewId(), BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.Nil(t, appErr)
mockChannelStore.AssertCalled(t, "GetChannelsByScheme", schemeID, 0, 1000)
mockChannelStore.AssertCalled(t, "GetChannelsByScheme", schemeID, 1000, 1000)
})
t.Run("GetChannelsByScheme store error propagates as AppError", func(t *testing.T) {
mainHelper.Parallel(t)
th := SetupWithStoreMock(t)
schemeID := model.NewId()
roleName := model.NewId()
scheme := &model.Scheme{Id: schemeID, Scope: model.SchemeScopeChannel}
mockStore := th.App.Srv().Store().(*mocks.Store)
mockSchemeStore := mocks.SchemeStore{}
mockChannelStore := mocks.ChannelStore{}
mockSchemeStore.On("Get", schemeID).Return(scheme, nil)
mockChannelStore.On("GetChannelsByScheme", schemeID, 0, 1000).Return(nil, errors.New("db error"))
mockStore.On("Scheme").Return(&mockSchemeStore)
mockStore.On("Channel").Return(&mockChannelStore)
role := &model.Role{Name: roleName, BuiltIn: false, SchemeId: &schemeID}
appErr := th.App.sendUpdatedRoleEvent(role)
require.NotNil(t, appErr)
})
}