From fbff94f3be1bf596f2b94f593687d3b162413de9 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Mon, 5 Mar 2018 07:18:22 -0500 Subject: MM-8604: emit config/license websocket events (#8371) --- api4/system.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'api4') diff --git a/api4/system.go b/api4/system.go index aab65bf20..c1541f0b5 100644 --- a/api4/system.go +++ b/api4/system.go @@ -8,7 +8,6 @@ import ( "io" "net/http" "runtime" - "strconv" l4g "github.com/alecthomas/log4go" "github.com/mattermost/mattermost-server/model" @@ -247,14 +246,7 @@ func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) { return } - respCfg := map[string]string{} - for k, v := range c.App.ClientConfig() { - respCfg[k] = v - } - - respCfg["NoAccounts"] = strconv.FormatBool(c.App.IsFirstUserAccount()) - - w.Write([]byte(model.MapToJson(respCfg))) + w.Write([]byte(model.MapToJson(c.App.ClientConfigWithNoAccounts()))) } func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) { -- cgit v1.2.3-1-g7c22 From 4a1802c039a0db2d97e8351c462963a99da857bf Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Mon, 5 Mar 2018 10:35:26 -0500 Subject: MM-9664 Add invalidation metrics for store caches (#8340) * Add invalidation metrics for store caches * Increment session invalidation metric * Fix tests --- api4/channel_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'api4') diff --git a/api4/channel_test.go b/api4/channel_test.go index e65918707..51c32cf71 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -13,7 +13,6 @@ import ( "testing" "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store/sqlstore" ) func TestCreateChannel(t *testing.T) { @@ -909,7 +908,7 @@ func TestDeleteChannel(t *testing.T) { // successful delete by channel admin th.MakeUserChannelAdmin(user, publicChannel6) th.MakeUserChannelAdmin(user, privateChannel7) - sqlstore.ClearChannelCaches() + th.App.Srv.Store.Channel().ClearCaches() _, resp = Client.DeleteChannel(publicChannel6.Id) CheckNoError(t, resp) @@ -960,7 +959,7 @@ func TestDeleteChannel(t *testing.T) { // // cannot delete by channel admin th.MakeUserChannelAdmin(user, publicChannel6) th.MakeUserChannelAdmin(user, privateChannel7) - sqlstore.ClearChannelCaches() + th.App.Srv.Store.Channel().ClearCaches() _, resp = Client.DeleteChannel(publicChannel6.Id) CheckForbiddenStatus(t, resp) @@ -1001,7 +1000,7 @@ func TestDeleteChannel(t *testing.T) { // cannot delete by channel admin th.MakeUserChannelAdmin(user, publicChannel6) th.MakeUserChannelAdmin(user, privateChannel7) - sqlstore.ClearChannelCaches() + th.App.Srv.Store.Channel().ClearCaches() _, resp = Client.DeleteChannel(publicChannel6.Id) CheckForbiddenStatus(t, resp) -- cgit v1.2.3-1-g7c22 From e8943936c51450540a4f2e8e7a2f3a2af90d14db Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 7 Mar 2018 12:36:40 -0600 Subject: general cleanup (#8387) --- api4/apitestlib.go | 27 --------------------------- api4/webhook.go | 1 - 2 files changed, 28 deletions(-) (limited to 'api4') diff --git a/api4/apitestlib.go b/api4/apitestlib.go index e55ca8c8b..2bb80ddfb 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -510,18 +510,6 @@ func CheckUserSanitization(t *testing.T, user *model.User) { } } -func CheckTeamSanitization(t *testing.T, team *model.Team) { - t.Helper() - - if team.Email != "" { - t.Fatal("email wasn't blank") - } - - if team.AllowedDomains != "" { - t.Fatal("'allowed domains' wasn't blank") - } -} - func CheckEtag(t *testing.T, data interface{}, resp *model.Response) { t.Helper() @@ -669,21 +657,6 @@ func CheckInternalErrorStatus(t *testing.T, resp *model.Response) { } } -func CheckPayLoadTooLargeStatus(t *testing.T, resp *model.Response) { - t.Helper() - - if resp.Error == nil { - t.Fatal("should have errored with status:" + strconv.Itoa(http.StatusRequestEntityTooLarge)) - return - } - - if resp.StatusCode != http.StatusRequestEntityTooLarge { - t.Log("actual: " + strconv.Itoa(resp.StatusCode)) - t.Log("expected: " + strconv.Itoa(http.StatusRequestEntityTooLarge)) - t.Fatal("wrong status code") - } -} - func readTestFile(name string) ([]byte, error) { path, _ := utils.FindDir("tests") file, err := os.Open(path + "/" + name) diff --git a/api4/webhook.go b/api4/webhook.go index e19f14704..853cf43f3 100644 --- a/api4/webhook.go +++ b/api4/webhook.go @@ -510,7 +510,6 @@ func commandWebhook(c *Context, w http.ResponseWriter, r *http.Request) { } func decodePayload(payload io.Reader) (*model.IncomingWebhookRequest, *model.AppError) { - decodeError := &model.AppError{} incomingWebhookPayload, decodeError := model.IncomingWebhookRequestFromJson(payload) if decodeError != nil { -- cgit v1.2.3-1-g7c22 From 302dae5bb982aad14324a4df61a018557f3dd24e Mon Sep 17 00:00:00 2001 From: Stephen Kiers Date: Fri, 9 Mar 2018 05:48:30 -0700 Subject: MM-9274- Sort Users in Channel by status (#8181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * sort by lastActivity * added status ordering to Users * sort offline before dnd * remove data not needed * added seperate call for when order=‘status’ is on GetUser request * remove PrintLn * styling fix * remove mistake * mistake 2 * better comment * explicit if statemnt * writing tests * removed manually added mocks * generated mock * ICU-668 Added unit tests * style fix * sort by lastActivity * added status ordering to Users * sort offline before dnd * remove data not needed * added seperate call for when order=‘status’ is on GetUser request * remove PrintLn * styling fix * remove mistake * mistake 2 * better comment * explicit if statemnt * writing tests * removed manually added mocks * generated mock * ICU-668 Added unit tests * style fix * reverse dnd and offline * Fixed app.SaveStatusAndBroadcast * Fixed incorrect merge * Fixing incorrect merge again --- api4/apitestlib.go | 16 ++++++ api4/user.go | 14 ++++-- api4/user_test.go | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 3 deletions(-) (limited to 'api4') diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 2bb80ddfb..6edd37812 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -467,6 +467,22 @@ func (me *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) { utils.EnableDebugLogForTest() } +func (me *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember { + utils.DisableDebugLogForTest() + + member, err := me.App.AddUserToChannel(user, channel) + if err != nil { + l4g.Error(err.Error()) + l4g.Close() + time.Sleep(time.Second) + panic(err) + } + + utils.EnableDebugLogForTest() + + return member +} + func (me *TestHelper) GenerateTestEmail() string { if me.App.Config().EmailSettings.SMTPServer != "dockerhost" && os.Getenv("CI_INBUCKET_PORT") == "" { return strings.ToLower("success+" + model.NewId() + "@simulator.amazonses.com") diff --git a/api4/user.go b/api4/user.go index f82a6e3d5..8f8f08c75 100644 --- a/api4/user.go +++ b/api4/user.go @@ -290,16 +290,21 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - if sort != "" && sort != "last_activity_at" && sort != "create_at" { + if sort != "" && sort != "last_activity_at" && sort != "create_at" && sort != "status" { c.SetInvalidUrlParam("sort") return } // Currently only supports sorting on a team + // or sort="status" on inChannelId if (sort == "last_activity_at" || sort == "create_at") && (inTeamId == "" || notInTeamId != "" || inChannelId != "" || notInChannelId != "" || withoutTeam != "") { c.SetInvalidUrlParam("sort") return } + if sort == "status" && inChannelId == "" { + c.SetInvalidUrlParam("sort") + return + } var profiles []*model.User var err *model.AppError @@ -355,8 +360,11 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { c.SetPermissionError(model.PERMISSION_READ_CHANNEL) return } - - profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + if sort == "status" { + profiles, err = c.App.GetUsersInChannelPageByStatus(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } else { + profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } } else { // No permission check required diff --git a/api4/user_test.go b/api4/user_test.go index 4613a8ea9..f04cd6ab2 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -2650,3 +2650,146 @@ func TestUserAccessTokenDisableConfig(t *testing.T) { _, resp = Client.GetMe("") CheckNoError(t, resp) } + +func TestGetUsersByStatus(t *testing.T) { + th := Setup() + defer th.TearDown() + + team, err := th.App.CreateTeam(&model.Team{ + DisplayName: "dn_" + model.NewId(), + Name: GenerateTestTeamName(), + Email: th.GenerateTestEmail(), + Type: model.TEAM_OPEN, + }) + if err != nil { + t.Fatalf("failed to create team: %v", err) + } + + channel, err := th.App.CreateChannel(&model.Channel{ + DisplayName: "dn_" + model.NewId(), + Name: "name_" + model.NewId(), + Type: model.CHANNEL_OPEN, + TeamId: team.Id, + CreatorId: model.NewId(), + }, false) + if err != nil { + t.Fatalf("failed to create channel: %v", err) + } + + createUserWithStatus := func(username string, status string) *model.User { + id := model.NewId() + + user, err := th.App.CreateUser(&model.User{ + Email: "success+" + id + "@simulator.amazonses.com", + Username: "un_" + username + "_" + id, + Nickname: "nn_" + id, + Password: "Password1", + }) + if err != nil { + t.Fatalf("failed to create user: %v", err) + } + + th.LinkUserToTeam(user, team) + th.AddUserToChannel(user, channel) + + th.App.SaveAndBroadcastStatus(&model.Status{ + UserId: user.Id, + Status: status, + Manual: true, + }) + + return user + } + + // Creating these out of order in case that affects results + offlineUser1 := createUserWithStatus("offline1", model.STATUS_OFFLINE) + offlineUser2 := createUserWithStatus("offline2", model.STATUS_OFFLINE) + awayUser1 := createUserWithStatus("away1", model.STATUS_AWAY) + awayUser2 := createUserWithStatus("away2", model.STATUS_AWAY) + onlineUser1 := createUserWithStatus("online1", model.STATUS_ONLINE) + onlineUser2 := createUserWithStatus("online2", model.STATUS_ONLINE) + dndUser1 := createUserWithStatus("dnd1", model.STATUS_DND) + dndUser2 := createUserWithStatus("dnd2", model.STATUS_DND) + + client := th.CreateClient() + if _, resp := client.Login(onlineUser2.Username, "Password1"); resp.Error != nil { + t.Fatal(resp.Error) + } + + t.Run("sorting by status then alphabetical", func(t *testing.T) { + usersByStatus, resp := client.GetUsersInChannelByStatus(channel.Id, 0, 8, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + expectedUsersByStatus := []*model.User{ + onlineUser1, + onlineUser2, + awayUser1, + awayUser2, + dndUser1, + dndUser2, + offlineUser1, + offlineUser2, + } + + if len(usersByStatus) != len(expectedUsersByStatus) { + t.Fatalf("received only %v users, expected %v", len(usersByStatus), len(expectedUsersByStatus)) + } + + for i := range usersByStatus { + if usersByStatus[i].Id != expectedUsersByStatus[i].Id { + t.Fatalf("received user %v at index %v, expected %v", usersByStatus[i].Username, i, expectedUsersByStatus[i].Username) + } + } + }) + + t.Run("paging", func(t *testing.T) { + usersByStatus, resp := client.GetUsersInChannelByStatus(channel.Id, 0, 3, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + if len(usersByStatus) != 3 { + t.Fatal("received too many users") + } + + if usersByStatus[0].Id != onlineUser1.Id && usersByStatus[1].Id != onlineUser2.Id { + t.Fatal("expected to receive online users first") + } + + if usersByStatus[2].Id != awayUser1.Id { + t.Fatal("expected to receive away users second") + } + + usersByStatus, resp = client.GetUsersInChannelByStatus(channel.Id, 1, 3, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + if usersByStatus[0].Id != awayUser2.Id { + t.Fatal("expected to receive away users second") + } + + if usersByStatus[1].Id != dndUser1.Id && usersByStatus[2].Id != dndUser2.Id { + t.Fatal("expected to receive dnd users third") + } + + usersByStatus, resp = client.GetUsersInChannelByStatus(channel.Id, 1, 4, "") + if resp.Error != nil { + t.Fatal(resp.Error) + } + + if len(usersByStatus) != 4 { + t.Fatal("received too many users") + } + + if usersByStatus[0].Id != dndUser1.Id && usersByStatus[1].Id != dndUser2.Id { + t.Fatal("expected to receive dnd users third") + } + + if usersByStatus[2].Id != offlineUser1.Id && usersByStatus[3].Id != offlineUser2.Id { + t.Fatal("expected to receive offline users last") + } + }) +} -- cgit v1.2.3-1-g7c22 From 4e26594fcb03c378222d2316a004c291d48dd6c7 Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Mon, 12 Mar 2018 10:21:20 -0400 Subject: Removed mssola/user_agent library (#8417) * Removed mssola/user_agent library * Changed user agent tests to use t.Run --- api4/compliance.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'api4') diff --git a/api4/compliance.go b/api4/compliance.go index 71f0fa81d..4035afb77 100644 --- a/api4/compliance.go +++ b/api4/compliance.go @@ -7,8 +7,8 @@ import ( "net/http" "strconv" + "github.com/avct/uasurfer" "github.com/mattermost/mattermost-server/model" - "github.com/mssola/user_agent" ) func (api *API) InitCompliance() { @@ -108,12 +108,11 @@ func downloadComplianceReport(c *Context, w http.ResponseWriter, r *http.Request w.Header().Del("Content-Type") // Content-Type will be set automatically by the http writer // attach extra headers to trigger a download on IE, Edge, and Safari - ua := user_agent.New(r.UserAgent()) - bname, _ := ua.Browser() + ua := uasurfer.Parse(r.UserAgent()) w.Header().Set("Content-Disposition", "attachment;filename=\""+job.JobName()+".zip\"") - if bname == "Edge" || bname == "Internet Explorer" || bname == "Safari" { + if ua.Browser.Name == uasurfer.BrowserIE || ua.Browser.Name == uasurfer.BrowserSafari { // trim off anything before the final / so we just get the file's name w.Header().Set("Content-Type", "application/octet-stream") } -- cgit v1.2.3-1-g7c22