From 34668511cf6eed92d790909be8d22a2b2b2ccf1b Mon Sep 17 00:00:00 2001 From: Hossein Ahmadian-Yazdi Date: Fri, 6 Mar 2020 15:58:14 -0500 Subject: [PATCH 1/5] fix read only channel when join channel (#13946) Co-authored-by: mattermod --- app/channel.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/channel.go b/app/channel.go index 2ee89a6466..fc3c918728 100644 --- a/app/channel.go +++ b/app/channel.go @@ -1164,7 +1164,8 @@ func (a *App) addUserToChannel(user *model.User, channel *model.Channel, teamMem newMember.SchemeAdmin = userShouldBeAdmin } - if _, err = a.Srv().Store.Channel().SaveMember(newMember); err != nil { + newMember, err = a.Srv().Store.Channel().SaveMember(newMember) + if err != nil { mlog.Error("Failed to add member", mlog.String("user_id", user.Id), mlog.String("channel_id", channel.Id), mlog.Err(err)) return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "", http.StatusInternalServerError) } From c8a923d9e3fe039a5239aaa9a990ef4a02a686a5 Mon Sep 17 00:00:00 2001 From: Mario de Frutos Dieguez Date: Sat, 7 Mar 2020 09:43:57 +0100 Subject: [PATCH 2/5] MM-22247: Space in content-type breaks integration with 3rd party apps (#13839) --- web/webhook.go | 11 ++++++++--- web/webhook_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/web/webhook.go b/web/webhook.go index 1e33b367d3..cf000160a2 100644 --- a/web/webhook.go +++ b/web/webhook.go @@ -5,6 +5,7 @@ package web import ( "io" + "mime" "net/http" "strings" @@ -28,7 +29,11 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { var err *model.AppError incomingWebhookPayload := &model.IncomingWebhookRequest{} - contentType := r.Header.Get("Content-Type") + mediaType, _, mimeErr := mime.ParseMediaType(r.Header.Get("Content-Type")) + if mimeErr != nil && mimeErr != mime.ErrInvalidMediaParameter { + c.Err = model.NewAppError("incomingWebhook", "api.webhook.incoming.error", nil, mimeErr.Error(), http.StatusBadRequest) + return + } defer func() { if *c.App.Config().LogSettings.EnableWebhookDebugging { @@ -38,7 +43,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { } }() - if strings.Split(contentType, "; ")[0] == "application/x-www-form-urlencoded" { + if mediaType == "application/x-www-form-urlencoded" { payload := strings.NewReader(r.FormValue("payload")) incomingWebhookPayload, err = decodePayload(payload) @@ -46,7 +51,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - } else if strings.HasPrefix(contentType, "multipart/form-data") { + } else if mediaType == "multipart/form-data" { r.ParseMultipartForm(0) decoder := schema.NewDecoder() diff --git a/web/webhook_test.go b/web/webhook_test.go index 47a7e88d16..1e918cf24b 100644 --- a/web/webhook_test.go +++ b/web/webhook_test.go @@ -87,14 +87,42 @@ func TestIncomingWebhook(t *testing.T) { assert.Nil(t, err) assert.True(t, resp.StatusCode == http.StatusOK) + resp, err = http.Post(url, "AppLicaTion/x-www-Form-urlencoded", strings.NewReader("payload={\"text\":\""+text+"\"}")) + assert.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusOK) + + resp, err = http.Post(url, "application/x-www-form-urlencoded;charset=utf-8", strings.NewReader("payload={\"text\":\""+text+"\"}")) + assert.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusOK) + + resp, err = http.Post(url, "application/x-www-form-urlencoded; charset=utf-8", strings.NewReader("payload={\"text\":\""+text+"\"}")) + assert.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusOK) + + resp, err = http.Post(url, "application/x-www-form-urlencoded wrongtext", strings.NewReader("payload={\"text\":\""+text+"\"}")) + assert.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusBadRequest) + resp, err = http.Post(url, "application/json", strings.NewReader("{\"text\":\""+tooLongText+"\"}")) require.Nil(t, err) assert.True(t, resp.StatusCode == http.StatusOK) + resp, err = http.Post(url, "application/x-www-form-urlencoded", strings.NewReader("{\"text\":\""+tooLongText+"\"}")) + assert.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusBadRequest) + + resp, err = http.Post(url, "application/json", strings.NewReader("payload={\"text\":\""+text+"\"}")) + assert.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusBadRequest) + payloadMultiPart := "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\nwebhook-bot\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"text\"\r\n\r\nthis is a test :tada:\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--" resp, err = http.Post(ApiClient.Url+"/hooks/"+hook.Id, "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", strings.NewReader(payloadMultiPart)) require.Nil(t, err) assert.True(t, resp.StatusCode == http.StatusOK) + + resp, err = http.Post(url, "mimetype/wrong", strings.NewReader("payload={\"text\":\""+text+"\"}")) + assert.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusBadRequest) }) t.Run("WebhookExperimentalReadOnly", func(t *testing.T) { From 0587c813e079070ad88e7ddb1f007881a6fd5b9e Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Sat, 7 Mar 2020 22:42:23 +0530 Subject: [PATCH 3/5] Fixing flaky test TestUnlinkGroupTeam (#14019) There is a race at the DB level where the goroutine c.App.SyncRolesAndMembership would set the the SchemeAdmin attribute to false. If this happens after UpdateUserToTeamAdmin happens and before the Login, then the user does not have the required permissions to unlink the group and it fails. Thanks to @streamer45 for spotting the issue. Co-authored-by: mattermod --- api4/group_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api4/group_test.go b/api4/group_test.go index a7ef53f265..e5e896651e 100644 --- a/api4/group_test.go +++ b/api4/group_test.go @@ -7,6 +7,7 @@ import ( "fmt" "net/http" "testing" + "time" "github.com/mattermost/mattermost-server/v5/model" "github.com/stretchr/testify/assert" @@ -236,6 +237,7 @@ func TestUnlinkGroupTeam(t *testing.T) { response = th.Client.UnlinkGroupSyncable(g.Id, th.BasicTeam.Id, model.GroupSyncableTypeTeam) assert.NotNil(t, response.Error) + time.Sleep(2 * time.Second) // A hack to let "go c.App.SyncRolesAndMembership" finish before moving on. th.UpdateUserToTeamAdmin(th.BasicUser, th.BasicTeam) ok, response := th.Client.Logout() assert.True(t, ok) From f2548d4e3d9bdba96446fb7f511f9fa94c9656b7 Mon Sep 17 00:00:00 2001 From: Carlos Tadeu Panato Junior Date: Mon, 9 Mar 2020 11:42:53 +0100 Subject: [PATCH 4/5] Upgrade 5.21 master (#13999) * db: updgrade db to 5.21 * db: prepare db upgrade for 5.22 Co-authored-by: mattermod --- store/sqlstore/upgrade.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/store/sqlstore/upgrade.go b/store/sqlstore/upgrade.go index 9cdccfeaff..28dd735304 100644 --- a/store/sqlstore/upgrade.go +++ b/store/sqlstore/upgrade.go @@ -18,7 +18,8 @@ import ( ) const ( - CURRENT_SCHEMA_VERSION = VERSION_5_20_0 + CURRENT_SCHEMA_VERSION = VERSION_5_21_0 + VERSION_5_21_0 = "5.21.0" VERSION_5_20_0 = "5.20.0" VERSION_5_19_0 = "5.19.0" VERSION_5_18_0 = "5.18.0" @@ -171,6 +172,8 @@ func upgradeDatabase(sqlStore SqlStore, currentModelVersionString string) error upgradeDatabaseToVersion518(sqlStore) upgradeDatabaseToVersion519(sqlStore) upgradeDatabaseToVersion520(sqlStore) + upgradeDatabaseToVersion521(sqlStore) + upgradeDatabaseToVersion522(sqlStore) return nil } @@ -762,3 +765,17 @@ func upgradeDatabaseToVersion520(sqlStore SqlStore) { saveSchemaVersion(sqlStore, VERSION_5_20_0) } } + +func upgradeDatabaseToVersion521(sqlStore SqlStore) { + if shouldPerformUpgrade(sqlStore, VERSION_5_20_0, VERSION_5_21_0) { + saveSchemaVersion(sqlStore, VERSION_5_21_0) + } +} + +func upgradeDatabaseToVersion522(sqlStore SqlStore) { + // TODO: Uncomment following condition when version 5.22.0 is released + // if shouldPerformUpgrade(sqlStore, VERSION_5_21_0, VERSION_5_22_0) { + + // saveSchemaVersion(sqlStore, VERSION_5_22_0) + // } +} From b70d5df5c2c5973085f349bdb13dee3552d152f5 Mon Sep 17 00:00:00 2001 From: ABDUL SATTAR MAPARA <32198670+abdulsmapara@users.noreply.github.com> Date: Mon, 9 Mar 2020 19:43:02 +0530 Subject: [PATCH 5/5] Added documentation to a few methods of sql store 'SqlTeamStore' (#14016) * Added documentation to a few methods of sql store 'SqlTeamStore' * Update store/sqlstore/team_store.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> * Update store/sqlstore/team_store.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> * Added documentation to a few methods of sql store 'SqlTeamStore' * Corrected documentation for Save method * Updated store/sqlstore/team_store.go Co-Authored-By: Justine Geffen Co-authored-by: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> Co-authored-by: Justine Geffen --- store/sqlstore/team_store.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/store/sqlstore/team_store.go b/store/sqlstore/team_store.go index cf5555e963..9adc9917f4 100644 --- a/store/sqlstore/team_store.go +++ b/store/sqlstore/team_store.go @@ -188,6 +188,8 @@ func (s SqlTeamStore) createIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_teammembers_delete_at", "TeamMembers", "DeleteAt") } +// Save adds the team to the database if a team with the same name does not already +// exist in the database. It returns the team added if the operation is successful. func (s SqlTeamStore) Save(team *model.Team) (*model.Team, *model.AppError) { if len(team.Id) > 0 { return nil, model.NewAppError("SqlTeamStore.Save", @@ -209,6 +211,9 @@ func (s SqlTeamStore) Save(team *model.Team) (*model.Team, *model.AppError) { return team, nil } +// Update updates the details of the team passed as the parameter using the team Id +// if the team exists in the database. +// It returns the updated team if the operation is successful. func (s SqlTeamStore) Update(team *model.Team) (*model.Team, *model.AppError) { team.PreUpdate() @@ -528,6 +533,10 @@ func (s SqlTeamStore) getTeamMembersWithSchemeSelectQuery() sq.SelectBuilder { LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id") } +// SaveMember adds a team member using the team Id of the member +// if the member does not already exist in the database and if the number +// of existing team members are less than the maximum allowed users per team. +// It returns the team member added if the operation is successful. func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) (*model.TeamMember, *model.AppError) { defer s.InvalidateAllTeamIdsForUser(member.UserId) if err := member.IsValid(); err != nil { @@ -586,6 +595,8 @@ func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) return retrievedMember.ToModel(), nil } +// UpdateMember updates the team member if the team member exists in the database. +// It returns the updated team member if the operation is successful. func (s SqlTeamStore) UpdateMember(member *model.TeamMember) (*model.TeamMember, *model.AppError) { member.PreUpdate()