MM-65575: Fix server panic when bot posts trigger persistent notifications (#34174) (#34778)

* reproduce panic with test

* allow bots in the profile map

* explicitly prevent sending notifications to bots

* persistent notifications: handle senders not in the channel
Этот коммит содержится в:
Jesse Hallam
2025-12-17 11:06:57 -04:00
коммит произвёл GitHub
родитель e150243a7f
Коммит c9d60357db
5 изменённых файлов: 178 добавлений и 6 удалений

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

@@ -5,10 +5,12 @@ package app
import (
"testing"
"time"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/v8/channels/store"
storemocks "github.com/mattermost/mattermost/server/v8/channels/store/storetest/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
@@ -223,3 +225,106 @@ func TestSendPersistentNotifications(t *testing.T) {
err := th.App.SendPersistentNotifications()
require.NoError(t, err)
}
func TestSendPersistentNotificationsBotSender(t *testing.T) {
mainHelper.Parallel(t)
t.Run("should send notification when bot is sender", func(t *testing.T) {
th := Setup(t).InitBasic()
bot, appErr := th.App.CreateBot(th.Context, &model.Bot{
Username: "testbot",
DisplayName: "Test Bot",
OwnerId: th.BasicUser.Id,
})
require.Nil(t, appErr)
botUser, appErr := th.App.GetUser(bot.UserId)
require.Nil(t, appErr)
_, _, appErr = th.App.AddUserToTeam(th.Context, th.BasicTeam.Id, botUser.Id, "")
require.Nil(t, appErr)
_, appErr = th.App.AddUserToChannel(th.Context, botUser, th.BasicChannel, false)
require.Nil(t, appErr)
_, appErr = th.App.AddUserToChannel(th.Context, th.BasicUser2, th.BasicChannel, false)
require.Nil(t, appErr)
post := &model.Post{
UserId: bot.UserId,
ChannelId: th.BasicChannel.Id,
Message: "test " + "@" + th.BasicUser2.Username,
Metadata: &model.PostMetadata{
Priority: &model.PostPriority{
Priority: model.NewPointer(model.PostPriorityUrgent),
PersistentNotifications: model.NewPointer(true),
},
},
// Simulate old timestamp so persistent notifications are sent right away
CreateAt: time.Now().Add(-5 * time.Minute).UnixMilli(),
}
post, appErr = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
assert.EventuallyWithT(t, func(c *assert.CollectT) {
err := th.App.SendPersistentNotifications()
require.NoError(t, err)
persistentPostNotification, err := th.App.Srv().Store().PostPersistentNotification().GetSingle(post.Id)
require.NoError(c, err)
require.NotNil(c, persistentPostNotification)
assert.Greater(c, persistentPostNotification.SentCount, int16(0))
}, 5*time.Second, 100*time.Millisecond)
})
}
func TestSendPersistentNotificationsBotSenderNotInChannel(t *testing.T) {
mainHelper.Parallel(t)
t.Run("should send notification when bot sender is not a channel member", func(t *testing.T) {
th := Setup(t).InitBasic()
bot, appErr := th.App.CreateBot(th.Context, &model.Bot{
Username: "testbot",
DisplayName: "Test Bot",
OwnerId: th.BasicUser.Id,
})
require.Nil(t, appErr)
botUser, appErr := th.App.GetUser(bot.UserId)
require.Nil(t, appErr)
// Make the bot a system admin so it can post to channels it's not a member of
_, appErr = th.App.UpdateUserRoles(th.Context, botUser.Id, model.SystemUserRoleId+" "+model.SystemAdminRoleId, false)
require.Nil(t, appErr)
_, appErr = th.App.AddUserToChannel(th.Context, th.BasicUser2, th.BasicChannel, false)
require.Nil(t, appErr)
// Note: bot is NOT added to the team or channel
post := &model.Post{
UserId: bot.UserId,
ChannelId: th.BasicChannel.Id,
Message: "test " + "@" + th.BasicUser2.Username,
Metadata: &model.PostMetadata{
Priority: &model.PostPriority{
Priority: model.NewPointer(model.PostPriorityUrgent),
PersistentNotifications: model.NewPointer(true),
},
},
CreateAt: time.Now().Add(-5 * time.Minute).UnixMilli(),
}
post, appErr = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
assert.EventuallyWithT(t, func(c *assert.CollectT) {
err := th.App.SendPersistentNotifications()
require.NoError(t, err)
persistentPostNotification, err := th.App.Srv().Store().PostPersistentNotification().GetSingle(post.Id)
require.NoError(c, err)
require.NotNil(c, persistentPostNotification)
assert.Greater(c, persistentPostNotification.SentCount, int16(0))
}, 5*time.Second, 100*time.Millisecond)
})
}