mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[MM-57988] Fix move thread logic to not block channel admins (#27061)
* mm-57988: Allowing for channel admins to move thread * Fix the MoveThread team admin unit test that was introduced * Renaming the hasPermittedRole function to hasPermittedWranglerRole --------- Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
0da473b9f8
commit
cbd5d95bbb
@ -1160,15 +1160,20 @@ func moveThread(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// If there are no configured PermittedWranglerRoles, skip the check
|
||||
userHasRole := len(c.App.Config().WranglerSettings.PermittedWranglerRoles) == 0
|
||||
for _, role := range c.App.Config().WranglerSettings.PermittedWranglerRoles {
|
||||
if user.IsInRole(role) {
|
||||
userHasRole = true
|
||||
break
|
||||
}
|
||||
posts, _, err := c.App.GetPostsByIds([]string{c.Params.PostId})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
channelMember, err := c.App.GetChannelMember(c.AppContext, posts[0].ChannelId, user.Id)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
userHasRole := hasPermittedWranglerRole(c, user, channelMember)
|
||||
|
||||
// Sysadmins are always permitted
|
||||
if !userHasRole && !user.IsSystemAdmin() {
|
||||
c.Err = model.NewAppError("moveThread", "api.post.move_thread.no_permission", nil, "", http.StatusForbidden)
|
||||
@ -1267,3 +1272,19 @@ func getPostInfo(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
func hasPermittedWranglerRole(c *Context, user *model.User, channelMember *model.ChannelMember) bool {
|
||||
// If there are no configured PermittedWranglerRoles, skip the check
|
||||
if len(c.App.Config().WranglerSettings.PermittedWranglerRoles) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
userRoles := user.Roles + " " + channelMember.Roles
|
||||
for _, role := range c.App.Config().WranglerSettings.PermittedWranglerRoles {
|
||||
if model.IsInRole(userRoles, role) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -761,16 +761,20 @@ func TestMoveThread(t *testing.T) {
|
||||
basicUser2 := th.BasicUser2
|
||||
basicUser3 := th.CreateUser()
|
||||
|
||||
// Create a new public channel to move the post to
|
||||
publicChannel, resp, err := client.CreateChannel(ctx, &model.Channel{
|
||||
TeamId: th.BasicTeam.Id,
|
||||
Name: "test-public-channel",
|
||||
DisplayName: "Test Public Channel",
|
||||
Type: model.ChannelTypeOpen,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, publicChannel)
|
||||
// Helper function to create a new public channel to move the post to
|
||||
createPublicChannel := func(teamId, name, displayName string) *model.Channel {
|
||||
channel, resp, err := client.CreateChannel(ctx, &model.Channel{
|
||||
TeamId: teamId,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Type: model.ChannelTypeOpen,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, channel)
|
||||
|
||||
return channel
|
||||
}
|
||||
|
||||
// Create a new private channel to move the post to
|
||||
privateChannel, resp, err := client.CreateChannel(ctx, &model.Channel{
|
||||
@ -795,6 +799,9 @@ func TestMoveThread(t *testing.T) {
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, gmChannel)
|
||||
t.Run("Move to public channel", func(t *testing.T) {
|
||||
// Create a public channel
|
||||
publicChannel := createPublicChannel(th.BasicTeam.Id, "test-public-channel", "Test Public Channel")
|
||||
|
||||
// Create a new post to move
|
||||
post := &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
@ -971,6 +978,53 @@ func TestMoveThread(t *testing.T) {
|
||||
require.Equal(t, newPost.Message, posts.Posts[posts.Order[2]].Message)
|
||||
require.Equal(t, rootPost.Message, posts.Posts[posts.Order[3]].Message)
|
||||
})
|
||||
|
||||
t.Run("Move thread when permitted role is channel admin", func(t *testing.T) {
|
||||
// Create public channel
|
||||
publicChannel := createPublicChannel(th.BasicTeam.Id, "test-public-channel-admin", "Test Public Channel Admin")
|
||||
|
||||
// Set permitted role as channel admin
|
||||
enabled := true
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
cfg.WranglerSettings = model.WranglerSettings{MoveThreadToAnotherTeamEnable: &enabled,
|
||||
PermittedWranglerRoles: []string{model.PermissionsChannelAdmin}}
|
||||
})
|
||||
defer th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
cfg.WranglerSettings = model.WranglerSettings{}
|
||||
})
|
||||
|
||||
// Login as channel admin and add to channel
|
||||
th.LoginTeamAdmin()
|
||||
th.AddUserToChannel(th.TeamAdminUser, publicChannel)
|
||||
defer th.LoginBasic()
|
||||
|
||||
// Create a new post to move
|
||||
post := &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "test post",
|
||||
}
|
||||
newPost, resp, err := client.CreatePost(ctx, post)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, newPost)
|
||||
|
||||
// Move the post to the public channel
|
||||
moveThreadParams := &model.MoveThreadParams{
|
||||
ChannelId: publicChannel.Id,
|
||||
}
|
||||
resp, err = client.MoveThread(ctx, newPost.Id, moveThreadParams)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Check that the post was moved to the public channel
|
||||
posts, resp, err := client.GetPostsForChannel(ctx, publicChannel.Id, 0, 100, "", true, false)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, posts)
|
||||
// There should be 2 posts, the system join message for the user who moved it joining the channel, and the post we moved
|
||||
require.Equal(t, 2, len(posts.Posts))
|
||||
require.Equal(t, newPost.Message, posts.Posts[posts.Order[0]].Message)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreatePostPublic(t *testing.T) {
|
||||
|
@ -11,7 +11,7 @@ import {getCurrentUser} from 'mattermost-redux/selectors/entities/common';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {moveThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {arePreviewsCollapsed} from 'selectors/preferences';
|
||||
import {getGlobalItem} from 'selectors/storage';
|
||||
@ -64,10 +64,11 @@ export function makeCanWrangler() {
|
||||
'makeCanWrangler',
|
||||
getConfig,
|
||||
getCurrentUser,
|
||||
getCurrentUserRoles,
|
||||
moveThreadsEnabled,
|
||||
(_state: GlobalState, channelType: Channel['type']) => channelType,
|
||||
(_state: GlobalState, _channelType: Channel['type'], replyCount: number) => replyCount,
|
||||
(config: Partial<ClientConfig>, user: UserProfile, enabled: boolean, channelType: Channel['type'], replyCount: number) => {
|
||||
(config: Partial<ClientConfig>, user: UserProfile, userRoles: string, enabled: boolean, channelType: Channel['type'], replyCount: number) => {
|
||||
if (!enabled) {
|
||||
return false;
|
||||
}
|
||||
@ -90,8 +91,8 @@ export function makeCanWrangler() {
|
||||
allowedEmailDomains = WranglerAllowedEmailDomain?.split(',') || [];
|
||||
}
|
||||
|
||||
if (permittedUsers.length > 0 && !user.roles.includes('system_admin')) {
|
||||
const roles = user.roles.split(' ');
|
||||
if (permittedUsers.length > 0 && !userRoles.includes('system_admin')) {
|
||||
const roles = userRoles.split(' ');
|
||||
const hasRole = roles.some((role) => permittedUsers.includes(role));
|
||||
if (!hasRole) {
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user