Merge branch 'master' into mark-as-unread
Этот коммит содержится в:
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEchoCommand(t *testing.T) {
|
||||
@@ -20,20 +21,16 @@ func TestEchoCommand(t *testing.T) {
|
||||
|
||||
echoTestString := "/echo test"
|
||||
|
||||
if r1 := Client.Must(Client.ExecuteCommand(channel1.Id, echoTestString)).(*model.CommandResponse); r1 == nil {
|
||||
t.Fatal("Echo command failed to execute")
|
||||
}
|
||||
r1 := Client.Must(Client.ExecuteCommand(channel1.Id, echoTestString)).(*model.CommandResponse)
|
||||
require.NotNil(t, r1, "Echo command failed to execute")
|
||||
|
||||
if r1 := Client.Must(Client.ExecuteCommand(channel1.Id, "/echo ")).(*model.CommandResponse); r1 == nil {
|
||||
t.Fatal("Echo command failed to execute")
|
||||
}
|
||||
r1 = Client.Must(Client.ExecuteCommand(channel1.Id, "/echo ")).(*model.CommandResponse)
|
||||
require.NotNil(t, r1, "Echo command failed to execute")
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
p1 := Client.Must(Client.GetPostsForChannel(channel1.Id, 0, 2, "")).(*model.PostList)
|
||||
if len(p1.Order) != 2 {
|
||||
t.Fatal("Echo command failed to send")
|
||||
}
|
||||
require.Len(t, p1.Order, 2, "Echo command failed to send")
|
||||
}
|
||||
|
||||
func TestGroupmsgCommands(t *testing.T) {
|
||||
@@ -57,25 +54,18 @@ func TestGroupmsgCommands(t *testing.T) {
|
||||
rs1 := Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/groupmsg "+user2.Username+","+user3.Username)).(*model.CommandResponse)
|
||||
|
||||
group1 := model.GetGroupNameFromUserIds([]string{user1.Id, user2.Id, user3.Id})
|
||||
|
||||
if !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+group1) {
|
||||
t.Fatal("failed to create group channel")
|
||||
}
|
||||
require.True(t, strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+group1), "failed to create group channel")
|
||||
|
||||
rs2 := Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/groupmsg "+user3.Username+","+user4.Username+" foobar")).(*model.CommandResponse)
|
||||
group2 := model.GetGroupNameFromUserIds([]string{user1.Id, user3.Id, user4.Id})
|
||||
|
||||
if !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+group2) {
|
||||
t.Fatal("failed to create second direct channel")
|
||||
}
|
||||
if result := Client.Must(Client.SearchPosts(team.Id, "foobar", false)).(*model.PostList); len(result.Order) == 0 {
|
||||
t.Fatal("post did not get sent to direct message")
|
||||
}
|
||||
require.True(t, strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+group2), "failed to create second direct channel")
|
||||
|
||||
result := Client.Must(Client.SearchPosts(team.Id, "foobar", false)).(*model.PostList)
|
||||
require.NotEqual(t, 0, len(result.Order), "post did not get sent to direct message")
|
||||
|
||||
rs3 := Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/groupmsg "+user2.Username+","+user3.Username)).(*model.CommandResponse)
|
||||
if !strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+group1) {
|
||||
t.Fatal("failed to go back to existing group channel")
|
||||
}
|
||||
require.True(t, strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+group1), "failed to go back to existing group channel")
|
||||
|
||||
Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/groupmsg "+user2.Username+" foobar"))
|
||||
Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/groupmsg "+user2.Username+","+user3.Username+","+user4.Username+","+user5.Username+","+user6.Username+","+user7.Username+","+user8.Username+","+user9.Username+" foobar"))
|
||||
@@ -91,19 +81,13 @@ func TestInvitePeopleCommand(t *testing.T) {
|
||||
channel := th.BasicChannel
|
||||
|
||||
r1 := Client.Must(Client.ExecuteCommand(channel.Id, "/invite_people test@example.com")).(*model.CommandResponse)
|
||||
if r1 == nil {
|
||||
t.Fatal("Command failed to execute")
|
||||
}
|
||||
require.NotNil(t, r1, "Command failed to execute")
|
||||
|
||||
r2 := Client.Must(Client.ExecuteCommand(channel.Id, "/invite_people test1@example.com test2@example.com")).(*model.CommandResponse)
|
||||
if r2 == nil {
|
||||
t.Fatal("Command failed to execute")
|
||||
}
|
||||
require.NotNil(t, r2, "Command failed to execute")
|
||||
|
||||
r3 := Client.Must(Client.ExecuteCommand(channel.Id, "/invite_people")).(*model.CommandResponse)
|
||||
if r3 == nil {
|
||||
t.Fatal("Command failed to execute")
|
||||
}
|
||||
require.NotNil(t, r3, "Command failed to execute")
|
||||
}
|
||||
|
||||
// also used to test /open (see command_open_test.go)
|
||||
@@ -129,14 +113,10 @@ func testJoinCommands(t *testing.T, alias string) {
|
||||
channel3 := Client.Must(Client.CreateDirectChannel(th.BasicUser.Id, user2.Id)).(*model.Channel)
|
||||
|
||||
rs5 := Client.Must(Client.ExecuteCommand(channel0.Id, "/"+alias+" "+channel2.Name)).(*model.CommandResponse)
|
||||
if !strings.HasSuffix(rs5.GotoLocation, "/"+team.Name+"/channels/"+channel2.Name) {
|
||||
t.Fatal("failed to join channel")
|
||||
}
|
||||
require.True(t, strings.HasSuffix(rs5.GotoLocation, "/"+team.Name+"/channels/"+channel2.Name), "failed to join channel")
|
||||
|
||||
rs6 := Client.Must(Client.ExecuteCommand(channel0.Id, "/"+alias+" "+channel3.Name)).(*model.CommandResponse)
|
||||
if strings.HasSuffix(rs6.GotoLocation, "/"+team.Name+"/channels/"+channel3.Name) {
|
||||
t.Fatal("should not have joined direct message channel")
|
||||
}
|
||||
require.False(t, strings.HasSuffix(rs6.GotoLocation, "/"+team.Name+"/channels/"+channel3.Name), "should not have joined direct message channel")
|
||||
|
||||
c1 := Client.Must(Client.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, "")).([]*model.Channel)
|
||||
|
||||
@@ -146,10 +126,7 @@ func testJoinCommands(t *testing.T, alias string) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Fatal("did not join channel")
|
||||
}
|
||||
require.True(t, found, "did not join channel")
|
||||
}
|
||||
|
||||
func TestJoinCommands(t *testing.T) {
|
||||
@@ -171,9 +148,7 @@ func TestLoadTestHelpCommands(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableTesting = true })
|
||||
|
||||
rs := Client.Must(Client.ExecuteCommand(channel.Id, "/test help")).(*model.CommandResponse)
|
||||
if !strings.Contains(rs.Text, "Mattermost testing commands to help") {
|
||||
t.Fatal(rs.Text)
|
||||
}
|
||||
require.True(t, strings.Contains(rs.Text, "Mattermost testing commands to help"), rs.Text)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
@@ -193,9 +168,7 @@ func TestLoadTestSetupCommands(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableTesting = true })
|
||||
|
||||
rs := Client.Must(Client.ExecuteCommand(channel.Id, "/test setup fuzz 1 1 1")).(*model.CommandResponse)
|
||||
if rs.Text != "Created environment" {
|
||||
t.Fatal(rs.Text)
|
||||
}
|
||||
require.Equal(t, "Created environment", rs.Text, rs.Text)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
@@ -215,9 +188,7 @@ func TestLoadTestUsersCommands(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableTesting = true })
|
||||
|
||||
rs := Client.Must(Client.ExecuteCommand(channel.Id, "/test users fuzz 1 2")).(*model.CommandResponse)
|
||||
if rs.Text != "Added users" {
|
||||
t.Fatal(rs.Text)
|
||||
}
|
||||
require.Equal(t, "Added users", rs.Text, rs.Text)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
@@ -237,9 +208,7 @@ func TestLoadTestChannelsCommands(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableTesting = true })
|
||||
|
||||
rs := Client.Must(Client.ExecuteCommand(channel.Id, "/test channels fuzz 1 2")).(*model.CommandResponse)
|
||||
if rs.Text != "Added channels" {
|
||||
t.Fatal(rs.Text)
|
||||
}
|
||||
require.Equal(t, "Added channels", rs.Text, rs.Text)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
@@ -259,9 +228,7 @@ func TestLoadTestPostsCommands(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableTesting = true })
|
||||
|
||||
rs := Client.Must(Client.ExecuteCommand(channel.Id, "/test posts fuzz 2 3 2")).(*model.CommandResponse)
|
||||
if rs.Text != "Added posts" {
|
||||
t.Fatal(rs.Text)
|
||||
}
|
||||
require.Equal(t, "Added posts", rs.Text, rs.Text)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
@@ -286,19 +253,13 @@ func TestLeaveCommands(t *testing.T) {
|
||||
channel3 := Client.Must(Client.CreateDirectChannel(th.BasicUser.Id, user2.Id)).(*model.Channel)
|
||||
|
||||
rs1 := Client.Must(Client.ExecuteCommand(channel1.Id, "/leave")).(*model.CommandResponse)
|
||||
if !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+model.DEFAULT_CHANNEL) {
|
||||
t.Fatal("failed to leave open channel 1")
|
||||
}
|
||||
require.True(t, strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+model.DEFAULT_CHANNEL), "failed to leave open channel 1")
|
||||
|
||||
rs2 := Client.Must(Client.ExecuteCommand(channel2.Id, "/leave")).(*model.CommandResponse)
|
||||
if !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+model.DEFAULT_CHANNEL) {
|
||||
t.Fatal("failed to leave private channel 1")
|
||||
}
|
||||
require.True(t, strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+model.DEFAULT_CHANNEL), "failed to leave private channel 1")
|
||||
|
||||
_, err := Client.ExecuteCommand(channel3.Id, "/leave")
|
||||
if err == nil {
|
||||
t.Fatal("should fail leaving direct channel")
|
||||
}
|
||||
require.NotNil(t, err, "should fail leaving direct channel")
|
||||
|
||||
cdata := Client.Must(Client.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, "")).([]*model.Channel)
|
||||
|
||||
@@ -308,16 +269,12 @@ func TestLeaveCommands(t *testing.T) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
t.Fatal("did not leave right channels")
|
||||
}
|
||||
require.False(t, found, "did not leave right channels")
|
||||
|
||||
for _, c := range cdata {
|
||||
if c.Name == model.DEFAULT_CHANNEL {
|
||||
if _, err := Client.RemoveUserFromChannel(c.Id, th.BasicUser.Id); err == nil {
|
||||
t.Fatal("should have errored on leaving default channel")
|
||||
}
|
||||
_, err := Client.RemoveUserFromChannel(c.Id, th.BasicUser.Id)
|
||||
require.NotNil(t, err, "should have errored on leaving default channel")
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -340,28 +297,19 @@ func TestMeCommand(t *testing.T) {
|
||||
testString := "/me hello"
|
||||
|
||||
r1 := Client.Must(Client.ExecuteCommand(channel.Id, testString)).(*model.CommandResponse)
|
||||
if r1 == nil {
|
||||
t.Fatal("Command failed to execute")
|
||||
}
|
||||
require.NotNil(t, r1, "Command failed to execute")
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
p1 := Client.Must(Client.GetPostsForChannel(channel.Id, 0, 2, "")).(*model.PostList)
|
||||
if len(p1.Order) != 2 {
|
||||
t.Fatal("Command failed to send")
|
||||
} else {
|
||||
pt := p1.Posts[p1.Order[0]].Type
|
||||
if pt != model.POST_ME {
|
||||
t.Log(pt)
|
||||
t.Fatalf("invalid post type, got '%s', wanted '%s'", pt, model.POST_ME)
|
||||
}
|
||||
msg := p1.Posts[p1.Order[0]].Message
|
||||
want := "*hello*"
|
||||
if msg != want {
|
||||
t.Log(msg)
|
||||
t.Fatalf("invalid me response message, got '%s', wanted '%s'", msg, want)
|
||||
}
|
||||
}
|
||||
require.Len(t, p1.Order, 2, "Command failed to send")
|
||||
|
||||
pt := p1.Posts[p1.Order[0]].Type
|
||||
require.Equal(t, model.POST_ME, pt, "invalid post type")
|
||||
|
||||
msg := p1.Posts[p1.Order[0]].Message
|
||||
want := "*hello*"
|
||||
require.Equal(t, want, msg, "invalid me response")
|
||||
}
|
||||
|
||||
func TestMsgCommands(t *testing.T) {
|
||||
@@ -379,22 +327,25 @@ func TestMsgCommands(t *testing.T) {
|
||||
Client.Must(Client.CreateDirectChannel(th.BasicUser.Id, user3.Id))
|
||||
|
||||
rs1 := Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/msg "+user2.Username)).(*model.CommandResponse)
|
||||
if !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) && !strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id) {
|
||||
t.Fatal("failed to create direct channel")
|
||||
}
|
||||
require.Condition(t, func() bool {
|
||||
return strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) ||
|
||||
strings.HasSuffix(rs1.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id)
|
||||
}, "failed to create direct channel")
|
||||
|
||||
rs2 := Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/msg "+user3.Username+" foobar")).(*model.CommandResponse)
|
||||
if !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user3.Id) && !strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user3.Id+"__"+user1.Id) {
|
||||
t.Fatal("failed to create second direct channel")
|
||||
}
|
||||
if result := Client.Must(Client.SearchPosts(th.BasicTeam.Id, "foobar", false)).(*model.PostList); len(result.Order) == 0 {
|
||||
t.Fatalf("post did not get sent to direct message")
|
||||
}
|
||||
require.Condition(t, func() bool {
|
||||
return strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user3.Id) ||
|
||||
strings.HasSuffix(rs2.GotoLocation, "/"+team.Name+"/channels/"+user3.Id+"__"+user1.Id)
|
||||
}, "failed to create second direct channel")
|
||||
|
||||
result := Client.Must(Client.SearchPosts(th.BasicTeam.Id, "foobar", false)).(*model.PostList)
|
||||
require.NotEqual(t, 0, len(result.Order), "post did not get sent to direct message")
|
||||
|
||||
rs3 := Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/msg "+user2.Username)).(*model.CommandResponse)
|
||||
if !strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) && !strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id) {
|
||||
t.Fatal("failed to go back to existing direct channel")
|
||||
}
|
||||
require.Condition(t, func() bool {
|
||||
return strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user1.Id+"__"+user2.Id) ||
|
||||
strings.HasSuffix(rs3.GotoLocation, "/"+team.Name+"/channels/"+user2.Id+"__"+user1.Id)
|
||||
}, "failed to go back to existing direct channel")
|
||||
|
||||
Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/msg "+th.BasicUser.Username+" foobar"))
|
||||
Client.Must(Client.ExecuteCommand(th.BasicChannel.Id, "/msg junk foobar"))
|
||||
@@ -435,21 +386,13 @@ func TestShrugCommand(t *testing.T) {
|
||||
testString := "/shrug"
|
||||
|
||||
r1 := Client.Must(Client.ExecuteCommand(channel.Id, testString)).(*model.CommandResponse)
|
||||
if r1 == nil {
|
||||
t.Fatal("Command failed to execute")
|
||||
}
|
||||
require.NotNil(t, r1, "Command failed to execute")
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
p1 := Client.Must(Client.GetPostsForChannel(channel.Id, 0, 2, "")).(*model.PostList)
|
||||
if len(p1.Order) != 2 {
|
||||
t.Fatal("Command failed to send")
|
||||
} else {
|
||||
if p1.Posts[p1.Order[0]].Message != `¯\\\_(ツ)\_/¯` {
|
||||
t.Log(p1.Posts[p1.Order[0]].Message)
|
||||
t.Fatal("invalid shrug response")
|
||||
}
|
||||
}
|
||||
require.Len(t, p1.Order, 2, "Command failed to send")
|
||||
require.Equal(t, `¯\\\_(ツ)\_/¯`, p1.Posts[p1.Order[0]].Message, "invalid shrug response")
|
||||
}
|
||||
|
||||
func TestStatusCommands(t *testing.T) {
|
||||
@@ -467,15 +410,10 @@ func commandAndTest(t *testing.T, th *TestHelper, status string) {
|
||||
user := th.BasicUser
|
||||
|
||||
r1 := Client.Must(Client.ExecuteCommand(channel.Id, "/"+status)).(*model.CommandResponse)
|
||||
if r1 == nil {
|
||||
t.Fatal("Command failed to execute")
|
||||
}
|
||||
require.NotEqual(t, "Command failed to execute", r1)
|
||||
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
|
||||
rstatus := Client.Must(Client.GetUserStatus(user.Id, "")).(*model.Status)
|
||||
|
||||
if rstatus.Status != status {
|
||||
t.Fatal("Error setting status " + status)
|
||||
}
|
||||
require.Equal(t, status, rstatus.Status, "Error setting status")
|
||||
}
|
||||
|
||||
@@ -575,23 +575,40 @@ func getGroups(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.Err = model.NewAppError("Api4.getGroups", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
var teamID, channelID string
|
||||
|
||||
if id := c.Params.NotAssociatedToTeam; model.IsValidId(id) {
|
||||
teamID = id
|
||||
}
|
||||
|
||||
if id := c.Params.NotAssociatedToChannel; model.IsValidId(id) {
|
||||
channelID = id
|
||||
}
|
||||
|
||||
if teamID == "" && channelID == "" {
|
||||
c.Err = model.NewAppError("Api4.getGroups", "api.getGroups.invalid_or_missing_channel_or_team_id", nil, "", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
opts := model.GroupSearchOpts{
|
||||
Q: c.Params.Q,
|
||||
IncludeMemberCount: c.Params.IncludeMemberCount,
|
||||
}
|
||||
|
||||
teamID := c.Params.NotAssociatedToTeam
|
||||
if len(teamID) == 26 {
|
||||
if !c.App.SessionHasPermissionToTeam(c.App.Session, teamID, model.PERMISSION_VIEW_TEAM) {
|
||||
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
||||
if teamID != "" {
|
||||
_, err := c.App.GetTeam(teamID)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
if !c.App.SessionHasPermissionToTeam(c.App.Session, teamID, model.PERMISSION_MANAGE_TEAM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
|
||||
return
|
||||
}
|
||||
opts.NotAssociatedToTeam = teamID
|
||||
}
|
||||
|
||||
channelID := c.Params.NotAssociatedToChannel
|
||||
if len(channelID) == 26 {
|
||||
if channelID != "" {
|
||||
channel, err := c.App.GetChannel(channelID)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
|
||||
@@ -8,11 +8,9 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetGroup(t *testing.T) {
|
||||
@@ -765,6 +763,20 @@ func TestGetGroups(t *testing.T) {
|
||||
|
||||
th.App.SetLicense(model.NewTestLicense("ldap"))
|
||||
|
||||
_, response = th.SystemAdminClient.GetGroups(opts)
|
||||
CheckBadRequestStatus(t, response)
|
||||
|
||||
_, response = th.SystemAdminClient.UpdateChannelRoles(th.BasicChannel.Id, th.BasicUser.Id, "")
|
||||
require.Nil(t, response.Error)
|
||||
|
||||
opts.NotAssociatedToChannel = th.BasicChannel.Id
|
||||
|
||||
_, response = th.Client.GetGroups(opts)
|
||||
CheckForbiddenStatus(t, response)
|
||||
|
||||
_, response = th.SystemAdminClient.UpdateChannelRoles(th.BasicChannel.Id, th.BasicUser.Id, "channel_user channel_admin")
|
||||
require.Nil(t, response.Error)
|
||||
|
||||
groups, response := th.SystemAdminClient.GetGroups(opts)
|
||||
assert.Nil(t, response.Error)
|
||||
assert.ElementsMatch(t, []*model.Group{group, th.Group}, groups)
|
||||
@@ -787,7 +799,7 @@ func TestGetGroups(t *testing.T) {
|
||||
_, response = th.Client.GetGroups(opts)
|
||||
CheckForbiddenStatus(t, response)
|
||||
|
||||
_, response = th.SystemAdminClient.UpdateTeamMemberRoles(th.BasicTeam.Id, th.BasicUser.Id, "team_user")
|
||||
_, response = th.SystemAdminClient.UpdateTeamMemberRoles(th.BasicTeam.Id, th.BasicUser.Id, "team_user team_admin")
|
||||
require.Nil(t, response.Error)
|
||||
|
||||
_, response = th.Client.GetGroups(opts)
|
||||
|
||||
109
api4/plugin.go
109
api4/plugin.go
@@ -8,6 +8,7 @@ package api4
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -31,6 +32,7 @@ func (api *API) InitPlugin() {
|
||||
api.BaseRoutes.Plugins.Handle("", api.ApiSessionRequired(getPlugins)).Methods("GET")
|
||||
api.BaseRoutes.Plugin.Handle("", api.ApiSessionRequired(removePlugin)).Methods("DELETE")
|
||||
api.BaseRoutes.Plugins.Handle("/install_from_url", api.ApiSessionRequired(installPluginFromUrl)).Methods("POST")
|
||||
api.BaseRoutes.Plugins.Handle("/marketplace", api.ApiSessionRequired(installMarketplacePlugin)).Methods("POST")
|
||||
|
||||
api.BaseRoutes.Plugins.Handle("/statuses", api.ApiSessionRequired(getPluginStatuses)).Methods("GET")
|
||||
api.BaseRoutes.Plugin.Handle("/enable", api.ApiSessionRequired(enablePlugin)).Methods("POST")
|
||||
@@ -42,7 +44,8 @@ func (api *API) InitPlugin() {
|
||||
}
|
||||
|
||||
func uploadPlugin(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if !*c.App.Config().PluginSettings.Enable || !*c.App.Config().PluginSettings.EnableUploads {
|
||||
config := c.App.Config()
|
||||
if !*config.PluginSettings.Enable || !*config.PluginSettings.EnableUploads || *config.PluginSettings.RequirePluginSignature {
|
||||
c.Err = model.NewAppError("uploadPlugin", "app.plugin.upload_disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
@@ -81,19 +84,12 @@ func uploadPlugin(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if len(m.Value["force"]) > 0 && m.Value["force"][0] == "true" {
|
||||
force = true
|
||||
}
|
||||
manifest, unpackErr := c.App.InstallPlugin(file, force)
|
||||
|
||||
if unpackErr != nil {
|
||||
c.Err = unpackErr
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write([]byte(manifest.ToJson()))
|
||||
installPlugin(c, w, file, force)
|
||||
}
|
||||
|
||||
func installPluginFromUrl(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if !*c.App.Config().PluginSettings.Enable {
|
||||
if !*c.App.Config().PluginSettings.Enable || *c.App.Config().PluginSettings.RequirePluginSignature {
|
||||
c.Err = model.NewAppError("installPluginFromUrl", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
@@ -103,46 +99,57 @@ func installPluginFromUrl(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
force := r.URL.Query().Get("force") == "true"
|
||||
downloadUrl := r.URL.Query().Get("plugin_download_url")
|
||||
|
||||
if !model.IsValidHttpUrl(downloadUrl) {
|
||||
c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.invalid_url.app_error", nil, "", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
u, err := url.ParseRequestURI(downloadUrl)
|
||||
pluginFile, err := downloadFromUrl(c, downloadUrl)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.invalid_url.app_error", nil, "", http.StatusBadRequest)
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
if !*c.App.Config().PluginSettings.AllowInsecureDownloadUrl && u.Scheme != "https" {
|
||||
c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.insecure_url.app_error", nil, "", http.StatusBadRequest)
|
||||
installPlugin(c, w, pluginFile, force)
|
||||
}
|
||||
|
||||
func installMarketplacePlugin(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if !*c.App.Config().PluginSettings.Enable {
|
||||
c.Err = model.NewAppError("installMarketplacePlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
client := c.App.HTTPService.MakeClient(true)
|
||||
client.Timeout = INSTALL_PLUGIN_FROM_URL_HTTP_REQUEST_TIMEOUT
|
||||
if !*c.App.Config().PluginSettings.EnableMarketplace {
|
||||
c.Err = model.NewAppError("installMarketplacePlugin", "app.plugin.marketplace_disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.Get(downloadUrl)
|
||||
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
|
||||
pluginRequest, err := model.PluginRequestFromReader(r.Body)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.download_failed.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
c.Err = model.NewAppError("installMarketplacePlugin", "app.plugin.marketplace_plugin_request.app_error", nil, err.Error(), http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
force := false
|
||||
if r.URL.Query().Get("force") == "true" {
|
||||
force = true
|
||||
plugin, appErr := c.App.GetMarketplacePlugin(pluginRequest)
|
||||
if appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
|
||||
fileBytes, err := ioutil.ReadAll(resp.Body)
|
||||
pluginFile, appErr := downloadFromUrl(c, plugin.DownloadURL)
|
||||
if appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
signature, err := plugin.DecodeSignature()
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.reading_stream_failed.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
c.Err = model.NewAppError("installMarketplacePlugin", "app.plugin.signature_decode.app_error", nil, err.Error(), http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
manifest, appErr := c.App.InstallPlugin(bytes.NewReader(fileBytes), force)
|
||||
manifest, appErr := c.App.InstallPluginWithSignature(pluginFile, signature)
|
||||
if appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
@@ -348,3 +355,43 @@ func parseMarketplacePluginFilter(u *url.URL) (*model.MarketplacePluginFilter, e
|
||||
ServerVersion: serverVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func downloadFromUrl(c *Context, downloadUrl string) (io.ReadSeeker, *model.AppError) {
|
||||
if !model.IsValidHttpUrl(downloadUrl) {
|
||||
return nil, model.NewAppError("downloadFromUrl", "api.plugin.install.invalid_url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
u, err := url.ParseRequestURI(downloadUrl)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("downloadFromUrl", "api.plugin.install.invalid_url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
if !*c.App.Config().PluginSettings.AllowInsecureDownloadUrl && u.Scheme != "https" {
|
||||
return nil, model.NewAppError("downloadFromUrl", "api.plugin.install.insecure_url.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
client := c.App.HTTPService.MakeClient(true)
|
||||
client.Timeout = INSTALL_PLUGIN_FROM_URL_HTTP_REQUEST_TIMEOUT
|
||||
|
||||
resp, err := client.Get(downloadUrl)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("downloadFromUrl", "api.plugin.install.download_failed.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
fileBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("downloadFromUrl", "api.plugin.install.reading_stream_failed.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
return bytes.NewReader(fileBytes), nil
|
||||
}
|
||||
|
||||
func installPlugin(c *Context, w http.ResponseWriter, plugin io.ReadSeeker, force bool) {
|
||||
manifest, appErr := c.App.InstallPlugin(plugin, force)
|
||||
if appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write([]byte(manifest.ToJson()))
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package api4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@@ -206,7 +207,7 @@ func TestPlugin(t *testing.T) {
|
||||
|
||||
// Deactivate error case
|
||||
ok, resp = th.SystemAdminClient.DisablePlugin("junk")
|
||||
CheckBadRequestStatus(t, resp)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
assert.False(t, ok)
|
||||
|
||||
// Get error cases
|
||||
@@ -241,7 +242,7 @@ func TestPlugin(t *testing.T) {
|
||||
|
||||
// Remove error cases
|
||||
ok, resp = th.SystemAdminClient.RemovePlugin(manifest.Id)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
assert.False(t, ok)
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false })
|
||||
@@ -253,7 +254,7 @@ func TestPlugin(t *testing.T) {
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
_, resp = th.SystemAdminClient.RemovePlugin("bad.id")
|
||||
CheckBadRequestStatus(t, resp)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
}
|
||||
|
||||
func TestNotifyClusterPluginEvent(t *testing.T) {
|
||||
@@ -543,9 +544,9 @@ func TestGetInstalledMarketplacePlugins(t *testing.T) {
|
||||
samplePlugins := []*model.MarketplacePlugin{
|
||||
{
|
||||
BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
|
||||
HomepageURL: "https://github.com/mattermost/mattermost-plugin-nps",
|
||||
IconData: "http://example.com/icon.svg",
|
||||
DownloadURL: "https://github.com/mattermost/mattermost-plugin-nps/releases/download/v1.0.3/com.mattermost.nps-1.0.3.tar.gz",
|
||||
HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps",
|
||||
IconData: "https://example.com/icon.svg",
|
||||
DownloadURL: "https://example.com/mattermost/mattermost-plugin-nps/releases/download/v1.0.3/com.mattermost.nps-1.0.3.tar.gz",
|
||||
Manifest: &model.Manifest{
|
||||
Id: "com.mattermost.nps",
|
||||
Name: "User Satisfaction Surveys",
|
||||
@@ -671,9 +672,9 @@ func TestSearchGetMarketplacePlugins(t *testing.T) {
|
||||
samplePlugins := []*model.MarketplacePlugin{
|
||||
{
|
||||
BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
|
||||
HomepageURL: "https://github.com/mattermost/mattermost-plugin-nps",
|
||||
HomepageURL: "example.com/mattermost/mattermost-plugin-nps",
|
||||
IconData: "Cjxzdmcgdmlld0JveD0nMCAwIDEwNSA5MycgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz4KPHBhdGggZD0nTTY2LDBoMzl2OTN6TTM4LDBoLTM4djkzek01MiwzNWwyNSw1OGgtMTZsLTgtMThoLTE4eicgZmlsbD0nI0VEMUMyNCcvPgo8L3N2Zz4K",
|
||||
DownloadURL: "https://github.com/mattermost/mattermost-plugin-nps/releases/download/v1.0.3/com.mattermost.nps-1.0.3.tar.gz",
|
||||
DownloadURL: "example.com/mattermost/mattermost-plugin-nps/releases/download/v1.0.3/com.mattermost.nps-1.0.3.tar.gz",
|
||||
Manifest: &model.Manifest{
|
||||
Id: "com.mattermost.nps",
|
||||
Name: "User Satisfaction Surveys",
|
||||
@@ -769,6 +770,184 @@ func TestSearchGetMarketplacePlugins(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestInstallMarketplacePlugin(t *testing.T) {
|
||||
th := Setup().InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.Enable = true
|
||||
*cfg.PluginSettings.EnableUploads = true
|
||||
*cfg.PluginSettings.EnableMarketplace = false
|
||||
})
|
||||
path, _ := fileutils.FindDir("tests")
|
||||
signatureFilename := "testpluginv2.tar.gz.sig"
|
||||
signatureFileReader, err := os.Open(filepath.Join(path, signatureFilename))
|
||||
require.Nil(t, err)
|
||||
sigFile, err := ioutil.ReadAll(signatureFileReader)
|
||||
require.Nil(t, err)
|
||||
pluginSignature := base64.StdEncoding.EncodeToString(sigFile)
|
||||
|
||||
tarData, err := ioutil.ReadFile(filepath.Join(path, "testpluginv2.tar.gz"))
|
||||
require.NoError(t, err)
|
||||
pluginServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write(tarData)
|
||||
}))
|
||||
defer pluginServer.Close()
|
||||
|
||||
samplePlugins := []*model.MarketplacePlugin{
|
||||
{
|
||||
BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
|
||||
HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps",
|
||||
IconData: "https://example.com/icon.svg",
|
||||
DownloadURL: pluginServer.URL,
|
||||
Manifest: &model.Manifest{
|
||||
Id: "testplugin_v2",
|
||||
Name: "testplugin_v2",
|
||||
Description: "dsgsdg_v2",
|
||||
Version: "1.2.2",
|
||||
MinServerVersion: "",
|
||||
},
|
||||
},
|
||||
InstalledVersion: "",
|
||||
},
|
||||
{
|
||||
BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
|
||||
HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps",
|
||||
IconData: "https://example.com/icon.svg",
|
||||
DownloadURL: pluginServer.URL,
|
||||
Manifest: &model.Manifest{
|
||||
Id: "testplugin_v2",
|
||||
Name: "testplugin_v2",
|
||||
Description: "dsgsdg_v2",
|
||||
Version: "1.2.3",
|
||||
MinServerVersion: "",
|
||||
},
|
||||
Signature: pluginSignature,
|
||||
},
|
||||
InstalledVersion: "",
|
||||
},
|
||||
}
|
||||
request := &model.InstallMarketplacePluginRequest{Id: "", Version: ""}
|
||||
t.Run("marketplace disabled", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.EnableMarketplace = false
|
||||
*cfg.PluginSettings.MarketplaceUrl = "invalid.com"
|
||||
})
|
||||
plugin, resp := th.SystemAdminClient.InstallMarketplacePlugin(request)
|
||||
CheckNotImplementedStatus(t, resp)
|
||||
require.Nil(t, plugin)
|
||||
})
|
||||
t.Run("RequirePluginSignature enabled", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.Enable = true
|
||||
*cfg.PluginSettings.RequirePluginSignature = true
|
||||
})
|
||||
manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData))
|
||||
CheckNotImplementedStatus(t, resp)
|
||||
require.Nil(t, manifest)
|
||||
|
||||
manifest, resp = th.SystemAdminClient.InstallPluginFromUrl("some_url", true)
|
||||
CheckNotImplementedStatus(t, resp)
|
||||
require.Nil(t, manifest)
|
||||
})
|
||||
|
||||
t.Run("no server", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.EnableMarketplace = true
|
||||
*cfg.PluginSettings.MarketplaceUrl = "invalid.com"
|
||||
})
|
||||
|
||||
plugin, resp := th.SystemAdminClient.InstallMarketplacePlugin(request)
|
||||
CheckInternalErrorStatus(t, resp)
|
||||
require.Nil(t, plugin)
|
||||
})
|
||||
|
||||
t.Run("no permission", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.EnableMarketplace = true
|
||||
*cfg.PluginSettings.MarketplaceUrl = "invalid.com"
|
||||
})
|
||||
|
||||
plugin, resp := th.Client.InstallMarketplacePlugin(request)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
require.Nil(t, plugin)
|
||||
})
|
||||
|
||||
t.Run("plugin not found on the server", func(t *testing.T) {
|
||||
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||
res.WriteHeader(http.StatusOK)
|
||||
json, err := json.Marshal([]*model.MarketplacePlugin{})
|
||||
require.NoError(t, err)
|
||||
res.Write(json)
|
||||
}))
|
||||
defer testServer.Close()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.EnableMarketplace = true
|
||||
*cfg.PluginSettings.MarketplaceUrl = testServer.URL
|
||||
})
|
||||
pRequest := &model.InstallMarketplacePluginRequest{Id: "some_plugin_id", Version: "0.0.1"}
|
||||
plugin, resp := th.SystemAdminClient.InstallMarketplacePlugin(pRequest)
|
||||
CheckInternalErrorStatus(t, resp)
|
||||
require.Nil(t, plugin)
|
||||
})
|
||||
|
||||
t.Run("plugin not verified", func(t *testing.T) {
|
||||
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||
res.WriteHeader(http.StatusOK)
|
||||
json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[0]})
|
||||
require.NoError(t, err)
|
||||
res.Write(json)
|
||||
}))
|
||||
defer testServer.Close()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.EnableMarketplace = true
|
||||
*cfg.PluginSettings.MarketplaceUrl = testServer.URL
|
||||
*cfg.PluginSettings.AllowInsecureDownloadUrl = true
|
||||
})
|
||||
pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin_v2", Version: "1.2.2"}
|
||||
plugin, resp := th.SystemAdminClient.InstallMarketplacePlugin(pRequest)
|
||||
CheckInternalErrorStatus(t, resp)
|
||||
require.Nil(t, plugin)
|
||||
})
|
||||
|
||||
t.Run("verify, install and remove plugin", func(t *testing.T) {
|
||||
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||
res.WriteHeader(http.StatusOK)
|
||||
json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[1]})
|
||||
require.NoError(t, err)
|
||||
res.Write(json)
|
||||
}))
|
||||
defer testServer.Close()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.PluginSettings.EnableMarketplace = true
|
||||
*cfg.PluginSettings.MarketplaceUrl = testServer.URL
|
||||
})
|
||||
|
||||
pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin_v2", Version: "1.2.3"}
|
||||
manifest, resp := th.SystemAdminClient.InstallMarketplacePlugin(pRequest)
|
||||
CheckNoError(t, resp)
|
||||
require.NotNil(t, manifest)
|
||||
require.Equal(t, "testplugin_v2", manifest.Id)
|
||||
require.Equal(t, "1.2.3", manifest.Version)
|
||||
|
||||
filePath := filepath.Join(*th.App.Config().PluginSettings.Directory, "testplugin_v2.sig")
|
||||
savedSigFile, err := th.App.ReadFile(filePath)
|
||||
require.Nil(t, err)
|
||||
require.EqualValues(t, sigFile, savedSigFile)
|
||||
|
||||
ok, resp := th.SystemAdminClient.RemovePlugin(manifest.Id)
|
||||
CheckNoError(t, resp)
|
||||
assert.True(t, ok)
|
||||
exists, err := th.App.FileExists(filePath)
|
||||
require.Nil(t, err)
|
||||
require.False(t, exists)
|
||||
})
|
||||
}
|
||||
|
||||
func findClusterMessages(event string, msgs []*model.ClusterMessage) []*model.ClusterMessage {
|
||||
var result []*model.ClusterMessage
|
||||
for _, msg := range msgs {
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSaveReaction(t *testing.T) {
|
||||
@@ -34,35 +34,22 @@ func TestSaveReaction(t *testing.T) {
|
||||
t.Run("successful-reaction", func(t *testing.T) {
|
||||
rr, resp := Client.SaveReaction(reaction)
|
||||
CheckNoError(t, resp)
|
||||
require.Equal(t, reaction.UserId, rr.UserId, "UserId did not match")
|
||||
require.Equal(t, reaction.PostId, rr.PostId, "PostId did not match")
|
||||
require.Equal(t, reaction.EmojiName, rr.EmojiName, "EmojiName did not match")
|
||||
require.NotEqual(t, 0, rr.CreateAt, "CreateAt should exist")
|
||||
|
||||
if rr.UserId != reaction.UserId {
|
||||
t.Fatal("UserId did not match")
|
||||
}
|
||||
|
||||
if rr.PostId != reaction.PostId {
|
||||
t.Fatal("PostId did not match")
|
||||
}
|
||||
|
||||
if rr.EmojiName != reaction.EmojiName {
|
||||
t.Fatal("EmojiName did not match")
|
||||
}
|
||||
|
||||
if rr.CreateAt == 0 {
|
||||
t.Fatal("CreateAt should exist")
|
||||
}
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 1 {
|
||||
t.Fatal("didn't save reaction correctly")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "didn't save reaction correctly")
|
||||
})
|
||||
|
||||
t.Run("duplicated-reaction", func(t *testing.T) {
|
||||
_, resp := Client.SaveReaction(reaction)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 1 {
|
||||
t.Fatal("should have not save duplicated reaction")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have not save duplicated reaction")
|
||||
})
|
||||
|
||||
t.Run("save-second-reaction", func(t *testing.T) {
|
||||
@@ -70,14 +57,11 @@ func TestSaveReaction(t *testing.T) {
|
||||
|
||||
rr, resp := Client.SaveReaction(reaction)
|
||||
CheckNoError(t, resp)
|
||||
require.Equal(t, rr.EmojiName, reaction.EmojiName, "EmojiName did not match")
|
||||
|
||||
if rr.EmojiName != reaction.EmojiName {
|
||||
t.Fatal("EmojiName did not match")
|
||||
}
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 2 {
|
||||
t.Fatal("should have save multiple reactions")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err, "error saving multiple reactions")
|
||||
require.Equal(t, len(reactions), 2, "should have save multiple reactions")
|
||||
})
|
||||
|
||||
t.Run("saving-special-case", func(t *testing.T) {
|
||||
@@ -85,14 +69,11 @@ func TestSaveReaction(t *testing.T) {
|
||||
|
||||
rr, resp := Client.SaveReaction(reaction)
|
||||
CheckNoError(t, resp)
|
||||
require.Equal(t, reaction.EmojiName, rr.EmojiName, "EmojiName did not match")
|
||||
|
||||
if rr.EmojiName != reaction.EmojiName {
|
||||
t.Fatal("EmojiName did not match")
|
||||
}
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil && len(reactions) != 3 {
|
||||
t.Fatal("should have save multiple reactions")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 3, len(reactions), "should have save multiple reactions")
|
||||
})
|
||||
|
||||
t.Run("react-to-not-existing-post-id", func(t *testing.T) {
|
||||
@@ -167,9 +148,9 @@ func TestSaveReaction(t *testing.T) {
|
||||
_, resp := Client.SaveReaction(reaction)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 3 {
|
||||
t.Fatal("should have not created a reactions")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 3, len(reactions), "should have not created a reactions")
|
||||
th.AddPermissionToRole(model.PERMISSION_ADD_REACTION.Id, model.CHANNEL_USER_ROLE_ID)
|
||||
})
|
||||
|
||||
@@ -192,9 +173,9 @@ func TestSaveReaction(t *testing.T) {
|
||||
_, resp := Client.SaveReaction(reaction)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 0 {
|
||||
t.Fatal("should have not created a reaction")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(post.Id)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 0, len(reactions), "should have not created a reaction")
|
||||
|
||||
th.App.RemoveLicense()
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false })
|
||||
@@ -218,9 +199,9 @@ func TestSaveReaction(t *testing.T) {
|
||||
_, resp := Client.SaveReaction(reaction)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 0 {
|
||||
t.Fatal("should have not created a reaction")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(post.Id)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 0, len(reactions), "should have not created a reaction")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -263,11 +244,9 @@ func TestGetReactions(t *testing.T) {
|
||||
var reactions []*model.Reaction
|
||||
|
||||
for _, userReaction := range userReactions {
|
||||
if reaction, err := th.App.Srv.Store.Reaction().Save(userReaction); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
reactions = append(reactions, reaction)
|
||||
}
|
||||
reaction, err := th.App.Srv.Store.Reaction().Save(userReaction)
|
||||
require.Nil(t, err)
|
||||
reactions = append(reactions, reaction)
|
||||
}
|
||||
|
||||
t.Run("get-reactions", func(t *testing.T) {
|
||||
@@ -345,70 +324,68 @@ func TestDeleteReaction(t *testing.T) {
|
||||
|
||||
t.Run("delete-reaction", func(t *testing.T) {
|
||||
th.App.SaveReactionForPost(r1)
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
||||
t.Fatal("didn't save reaction correctly")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "didn't save reaction correctly")
|
||||
|
||||
ok, resp := Client.DeleteReaction(r1)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if !ok {
|
||||
t.Fatal("should have returned true")
|
||||
}
|
||||
require.True(t, ok, "should have returned true")
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 0 {
|
||||
t.Fatal("should have deleted reaction")
|
||||
}
|
||||
reactions, err = th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 0, len(reactions), "should have deleted reaction")
|
||||
})
|
||||
|
||||
t.Run("delete-reaction-when-post-has-multiple-reactions", func(t *testing.T) {
|
||||
th.App.SaveReactionForPost(r1)
|
||||
th.App.SaveReactionForPost(r2)
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
||||
t.Fatal("didn't save reactions correctly")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, len(reactions), 2, "didn't save reactions correctly")
|
||||
|
||||
_, resp := Client.DeleteReaction(r2)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 || *reactions[0] != *r1 {
|
||||
t.Fatal("should have deleted 1 reaction only")
|
||||
}
|
||||
reactions, err = th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have deleted only 1 reaction")
|
||||
require.Equal(t, *r1, *reactions[0], "should have deleted 1 reaction only")
|
||||
})
|
||||
|
||||
t.Run("delete-reaction-when-plus-one-reaction-name", func(t *testing.T) {
|
||||
th.App.SaveReactionForPost(r3)
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
||||
t.Fatal("didn't save reactions correctly")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 2, len(reactions), "didn't save reactions correctly")
|
||||
|
||||
_, resp := Client.DeleteReaction(r3)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 || *reactions[0] != *r1 {
|
||||
t.Fatal("should have deleted 1 reaction only")
|
||||
}
|
||||
reactions, err = th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have deleted 1 reaction only")
|
||||
require.Equal(t, *r1, *reactions[0], "should have deleted 1 reaction only")
|
||||
})
|
||||
|
||||
t.Run("delete-reaction-made-by-another-user", func(t *testing.T) {
|
||||
th.LoginBasic2()
|
||||
th.App.SaveReactionForPost(r4)
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
||||
t.Fatal("didn't save reaction correctly")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 2, len(reactions), "didn't save reaction correctly")
|
||||
|
||||
th.LoginBasic()
|
||||
|
||||
ok, resp := Client.DeleteReaction(r4)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if ok {
|
||||
t.Fatal("should have returned false")
|
||||
}
|
||||
require.False(t, ok, "should have returned false")
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 2 {
|
||||
t.Fatal("should have not deleted a reaction")
|
||||
}
|
||||
reactions, err = th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 2, len(reactions), "should have not deleted a reaction")
|
||||
})
|
||||
|
||||
t.Run("delete-reaction-from-not-existing-post-id", func(t *testing.T) {
|
||||
@@ -469,9 +446,9 @@ func TestDeleteReaction(t *testing.T) {
|
||||
_, resp = th.SystemAdminClient.DeleteReaction(r4)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 0 {
|
||||
t.Fatal("should have deleted both reactions")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 0, len(reactions), "should have deleted both reactions")
|
||||
})
|
||||
|
||||
t.Run("unable-to-delete-reaction-without-permissions", func(t *testing.T) {
|
||||
@@ -483,9 +460,9 @@ func TestDeleteReaction(t *testing.T) {
|
||||
_, resp := Client.DeleteReaction(r1)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
||||
t.Fatal("should have not deleted a reactions")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have not deleted a reactions")
|
||||
th.AddPermissionToRole(model.PERMISSION_REMOVE_REACTION.Id, model.CHANNEL_USER_ROLE_ID)
|
||||
})
|
||||
|
||||
@@ -496,9 +473,9 @@ func TestDeleteReaction(t *testing.T) {
|
||||
_, resp := th.SystemAdminClient.DeleteReaction(r1)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
||||
t.Fatal("should have not deleted a reactions")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have not deleted a reactions")
|
||||
th.AddPermissionToRole(model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id, model.SYSTEM_ADMIN_ROLE_ID)
|
||||
})
|
||||
|
||||
@@ -520,18 +497,18 @@ func TestDeleteReaction(t *testing.T) {
|
||||
r1, resp := Client.SaveReaction(reaction)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
||||
t.Fatal("should have created a reaction")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have created a reaction")
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true })
|
||||
|
||||
_, resp = th.SystemAdminClient.DeleteReaction(r1)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
||||
t.Fatal("should have not deleted a reaction")
|
||||
}
|
||||
reactions, err = th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have not deleted a reaction")
|
||||
|
||||
th.App.RemoveLicense()
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false })
|
||||
@@ -552,19 +529,19 @@ func TestDeleteReaction(t *testing.T) {
|
||||
r1, resp := Client.SaveReaction(reaction)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(postId); err != nil || len(reactions) != 1 {
|
||||
t.Fatal("should have created a reaction")
|
||||
}
|
||||
reactions, err := th.App.GetReactionsForPost(postId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have created a reaction")
|
||||
|
||||
err := th.App.DeleteChannel(channel, userId)
|
||||
err = th.App.DeleteChannel(channel, userId)
|
||||
assert.Nil(t, err)
|
||||
|
||||
_, resp = Client.SaveReaction(r1)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
if reactions, err := th.App.GetReactionsForPost(post.Id); err != nil || len(reactions) != 1 {
|
||||
t.Fatal("should have not deleted a reaction")
|
||||
}
|
||||
reactions, err = th.App.GetReactionsForPost(post.Id)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(reactions), "should have not deleted a reaction")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -618,12 +595,9 @@ func TestGetBulkReactions(t *testing.T) {
|
||||
|
||||
for _, userReaction := range userReactions {
|
||||
reactions := expectedPostIdsReactionsMap[userReaction.PostId]
|
||||
if reaction, err := th.App.Srv.Store.Reaction().Save(userReaction); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
reactions = append(reactions, reaction)
|
||||
|
||||
}
|
||||
reaction, err := th.App.Srv.Store.Reaction().Save(userReaction)
|
||||
require.Nil(t, err)
|
||||
reactions = append(reactions, reaction)
|
||||
expectedPostIdsReactionsMap[userReaction.PostId] = reactions
|
||||
}
|
||||
|
||||
|
||||
@@ -410,7 +410,27 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
err := c.App.SendAckToPushProxy(ack)
|
||||
if err != nil {
|
||||
if ack.NotificationType == model.PUSH_TYPE_ID_LOADED {
|
||||
if err != nil {
|
||||
// Log the error only, then continue to fetch notification message
|
||||
c.App.NotificationsLog.Error("Notification ack not sent to push proxy",
|
||||
mlog.String("ackId", ack.Id),
|
||||
mlog.String("type", ack.NotificationType),
|
||||
mlog.String("postId", ack.PostId),
|
||||
mlog.String("status", err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
msg, appErr := c.App.BuildFetchedPushNotificationMessage(ack.PostId, c.App.Session.UserId)
|
||||
if appErr != nil {
|
||||
c.Err = model.NewAppError("pushNotificationAck", "api.push_notification.id_loaded.fetch.app_error", nil, appErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write([]byte(msg.ToJson()))
|
||||
|
||||
return
|
||||
} else if err != nil {
|
||||
c.Err = model.NewAppError("pushNotificationAck", "api.push_notifications_ack.forward.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ func TestCreateTeamSanitization(t *testing.T) {
|
||||
rteam, resp := th.Client.CreateTeam(team)
|
||||
CheckNoError(t, resp)
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("system admin", func(t *testing.T) {
|
||||
@@ -116,6 +117,7 @@ func TestCreateTeamSanitization(t *testing.T) {
|
||||
rteam, resp := th.SystemAdminClient.CreateTeam(team)
|
||||
CheckNoError(t, resp)
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -187,18 +189,37 @@ func TestGetTeamSanitization(t *testing.T) {
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.Empty(t, rteam.Email, "should have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("team user without invite permissions", func(t *testing.T) {
|
||||
th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
|
||||
th.LinkUserToTeam(th.BasicUser2, team)
|
||||
|
||||
client := th.CreateClient()
|
||||
th.LoginBasic2WithClient(client)
|
||||
|
||||
rteam, resp := client.GetTeam(team.Id, "")
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.Empty(t, rteam.Email, "should have sanitized email")
|
||||
require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("team admin", func(t *testing.T) {
|
||||
rteam, resp := th.Client.GetTeam(team.Id, "")
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("system admin", func(t *testing.T) {
|
||||
rteam, resp := th.SystemAdminClient.GetTeam(team.Id, "")
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -337,13 +358,17 @@ func TestUpdateTeamSanitization(t *testing.T) {
|
||||
t.Run("team admin", func(t *testing.T) {
|
||||
rteam, resp := th.Client.UpdateTeam(team)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email for admin")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("system admin", func(t *testing.T) {
|
||||
rteam, resp := th.SystemAdminClient.UpdateTeam(team)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email for admin")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -421,13 +446,17 @@ func TestPatchTeamSanitization(t *testing.T) {
|
||||
t.Run("team admin", func(t *testing.T) {
|
||||
rteam, resp := th.Client.PatchTeam(team.Id, &model.TeamPatch{})
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email for admin")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("system admin", func(t *testing.T) {
|
||||
rteam, resp := th.SystemAdminClient.PatchTeam(team.Id, &model.TeamPatch{})
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email for admin")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -702,9 +731,11 @@ func TestGetAllTeamsSanitization(t *testing.T) {
|
||||
if rteam.Id == team.Id {
|
||||
teamFound = true
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email for team admin")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
} else if rteam.Id == team2.Id {
|
||||
team2Found = true
|
||||
require.Empty(t, rteam.Email, "should've sanitized email for non-admin")
|
||||
require.Empty(t, rteam.Email, "should have sanitized email for team admin")
|
||||
require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,6 +752,7 @@ func TestGetAllTeamsSanitization(t *testing.T) {
|
||||
}
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should not have sanitized inviteid")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -791,19 +823,40 @@ func TestGetTeamByNameSanitization(t *testing.T) {
|
||||
|
||||
rteam, resp := client.GetTeamByName(team.Name, "")
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.Empty(t, rteam.Email, "should've sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("team user without invite permissions", func(t *testing.T) {
|
||||
th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
|
||||
th.LinkUserToTeam(th.BasicUser2, team)
|
||||
|
||||
client := th.CreateClient()
|
||||
|
||||
th.LoginBasic2WithClient(client)
|
||||
|
||||
rteam, resp := client.GetTeam(team.Id, "")
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.Empty(t, rteam.Email, "should have sanitized email")
|
||||
require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("team admin/non-admin", func(t *testing.T) {
|
||||
rteam, resp := th.Client.GetTeamByName(team.Name, "")
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
})
|
||||
|
||||
t.Run("system admin", func(t *testing.T) {
|
||||
rteam, resp := th.SystemAdminClient.GetTeamByName(team.Name, "")
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -899,6 +952,7 @@ func TestSearchAllTeamsSanitization(t *testing.T) {
|
||||
for _, rteam := range rteams {
|
||||
require.Empty(t, rteam.Email, "should've sanitized email")
|
||||
require.Empty(t, rteam.AllowedDomains, "should've sanitized allowed domains")
|
||||
require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -913,6 +967,7 @@ func TestSearchAllTeamsSanitization(t *testing.T) {
|
||||
for _, rteam := range rteams {
|
||||
require.Empty(t, rteam.Email, "should've sanitized email")
|
||||
require.Empty(t, rteam.AllowedDomains, "should've sanitized allowed domains")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -922,6 +977,7 @@ func TestSearchAllTeamsSanitization(t *testing.T) {
|
||||
for _, rteam := range rteams {
|
||||
if rteam.Id == team.Id || rteam.Id == team2.Id || rteam.Id == th.BasicTeam.Id {
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -931,6 +987,7 @@ func TestSearchAllTeamsSanitization(t *testing.T) {
|
||||
CheckNoError(t, resp)
|
||||
for _, rteam := range rteams {
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1010,6 +1067,27 @@ func TestGetTeamsForUserSanitization(t *testing.T) {
|
||||
}
|
||||
|
||||
require.Empty(t, rteam.Email, "should've sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("team user without invite permissions", func(t *testing.T) {
|
||||
th.LinkUserToTeam(th.BasicUser2, team)
|
||||
th.LinkUserToTeam(th.BasicUser2, team2)
|
||||
|
||||
client := th.CreateClient()
|
||||
th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
|
||||
th.LoginBasic2WithClient(client)
|
||||
|
||||
rteams, resp := client.GetTeamsForUser(th.BasicUser2.Id, "")
|
||||
CheckNoError(t, resp)
|
||||
for _, rteam := range rteams {
|
||||
if rteam.Id != team.Id && rteam.Id != team2.Id {
|
||||
continue
|
||||
}
|
||||
|
||||
require.Empty(t, rteam.Email, "should have sanitized email")
|
||||
require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1022,6 +1100,7 @@ func TestGetTeamsForUserSanitization(t *testing.T) {
|
||||
}
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1034,6 +1113,7 @@ func TestGetTeamsForUserSanitization(t *testing.T) {
|
||||
}
|
||||
|
||||
require.NotEmpty(t, rteam.Email, "should not have sanitized email")
|
||||
require.NotEmpty(t, rteam.InviteId, "should have not sanitized inviteid")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1051,6 +1051,11 @@ func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if active && user.IsGuest() && !*c.App.Config().GuestAccountsSettings.Enable {
|
||||
c.Err = model.NewAppError("updateUserActive", "api.user.update_active.cannot_enable_guest_when_guest_feature_is_disabled.app_error", nil, "userId="+c.Params.UserId, http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = c.App.UpdateActive(user, active); err != nil {
|
||||
c.Err = err
|
||||
}
|
||||
|
||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Ссылка в новой задаче
Block a user