From 0896b5c64ef224f0f8835b9727d1c1b94cbe7c29 Mon Sep 17 00:00:00 2001 From: George Goldberg Date: Fri, 6 Jul 2018 09:07:36 +0100 Subject: MM-11106: Allow systeadmin webook to post to read only town square. (#9051) --- app/webhook.go | 11 ++++++++++- web/web_test.go | 15 ++++++++++----- web/webhook_test.go | 29 +++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/app/webhook.go b/app/webhook.go index c887fec97..8926c94a8 100644 --- a/app/webhook.go +++ b/app/webhook.go @@ -587,6 +587,8 @@ func (a *App) HandleIncomingWebhook(hookId string, req *model.IncomingWebhookReq hook = result.Data.(*model.IncomingWebhook) } + uchan := a.Srv.Store.User().Get(hook.UserId) + if len(req.Props) == 0 { req.Props = make(model.StringInterface) } @@ -637,8 +639,15 @@ func (a *App) HandleIncomingWebhook(hookId string, req *model.IncomingWebhookReq return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.channel_locked.app_error", nil, "", http.StatusForbidden) } + var user *model.User + if result := <-uchan; result.Err != nil { + return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message, http.StatusForbidden) + } else { + user = result.Data.(*model.User) + } + if a.License() != nil && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly && - channel.Name == model.DEFAULT_CHANNEL { + channel.Name == model.DEFAULT_CHANNEL && !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) { return model.NewAppError("HandleIncomingWebhook", "api.post.create_post.town_square_read_only", nil, "", http.StatusForbidden) } diff --git a/web/web_test.go b/web/web_test.go index b53ed9618..4befa8e37 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -37,10 +37,13 @@ func StopTestStore() { } type TestHelper struct { - App *app.App - BasicUser *model.User - BasicChannel *model.Channel - BasicTeam *model.Team + App *app.App + + BasicUser *model.User + BasicChannel *model.Channel + BasicTeam *model.Team + + SystemAdminUser *model.User } func Setup() *TestHelper { @@ -77,7 +80,9 @@ func Setup() *TestHelper { } func (th *TestHelper) InitBasic() *TestHelper { - user, _ := th.App.CreateUser(&model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", EmailVerified: true, Roles: model.SYSTEM_ADMIN_ROLE_ID}) + th.SystemAdminUser, _ = th.App.CreateUser(&model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", EmailVerified: true, Roles: model.SYSTEM_ADMIN_ROLE_ID}) + + user, _ := th.App.CreateUser(&model.User{Email: model.NewId() + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", EmailVerified: true, Roles: model.SYSTEM_USER_ROLE_ID}) team, _ := th.App.CreateTeam(&model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: user.Email, Type: model.TEAM_OPEN}) diff --git a/web/webhook_test.go b/web/webhook_test.go index 64ce7bf25..07fca70ed 100644 --- a/web/webhook_test.go +++ b/web/webhook_test.go @@ -97,13 +97,30 @@ func TestIncomingWebhook(t *testing.T) { assert.True(t, resp.StatusCode == http.StatusOK) }) - t.Run("WebhookExperimentReadOnly", func(t *testing.T) { - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false }) - _, err := http.Post(url, "application/json", strings.NewReader(fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"%s\"}", model.DEFAULT_CHANNEL))) - assert.Nil(t, err, "Not read only") - - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) + t.Run("WebhookExperimentalReadOnly", func(t *testing.T) { th.App.SetLicense(model.NewTestLicense()) + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) + + // Read only default channel should fail. + resp, err := http.Post(url, "application/json", strings.NewReader(fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"%s\"}", model.DEFAULT_CHANNEL))) + require.Nil(t, err) + assert.True(t, resp.StatusCode != http.StatusOK) + + // None-default channel should still work. + resp, err = http.Post(url, "application/json", strings.NewReader(fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"%s\"}", th.BasicChannel.Name))) + require.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusOK) + + // System-Admin Owned Hook + adminHook, err := th.App.CreateIncomingWebhookForChannel(th.SystemAdminUser.Id, th.BasicChannel, &model.IncomingWebhook{ChannelId: th.BasicChannel.Id}) + require.Nil(t, err) + adminUrl := ApiClient.Url + "/hooks/" + adminHook.Id + + resp, err = http.Post(adminUrl, "application/json", strings.NewReader(fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"%s\"}", model.DEFAULT_CHANNEL))) + require.Nil(t, err) + assert.True(t, resp.StatusCode == http.StatusOK) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = false }) }) t.Run("WebhookAttachments", func(t *testing.T) { -- cgit v1.2.3-1-g7c22