Merge branch 'master' into mark-as-unread

Этот коммит содержится в:
Harrison Healey
2019-11-19 09:45:03 -05:00
родитель 2f066da704 c40f0a4aea
Коммит de913e7537
108 изменённых файлов: 11124 добавлений и 1190 удалений

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

@@ -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)

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

@@ -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
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу