From b122381e87577ddfc12b792a3de9121ea830d50e Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 16 Aug 2017 07:17:57 -0500 Subject: PLT-1649: add response_url support for custom slash commands (#6739) * add response_url support for custom slash commands * pr suggestions * pr update / suggestion * test fix --- model/command_response.go | 17 +++++++++++ model/command_response_test.go | 24 ++++++++++++++++ model/command_webhook.go | 65 ++++++++++++++++++++++++++++++++++++++++++ model/command_webhook_test.go | 54 +++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 model/command_webhook.go create mode 100644 model/command_webhook_test.go (limited to 'model') diff --git a/model/command_response.go b/model/command_response.go index 27d39e173..0b80b297b 100644 --- a/model/command_response.go +++ b/model/command_response.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "io/ioutil" ) const ( @@ -31,6 +32,22 @@ func (o *CommandResponse) ToJson() string { } } +func CommandResponseFromHTTPBody(contentType string, body io.Reader) *CommandResponse { + if contentType == "application/json" { + return CommandResponseFromJson(body) + } + if b, err := ioutil.ReadAll(body); err == nil { + return CommandResponseFromPlainText(string(b)) + } + return nil +} + +func CommandResponseFromPlainText(text string) *CommandResponse { + return &CommandResponse{ + Text: text, + } +} + func CommandResponseFromJson(data io.Reader) *CommandResponse { decoder := json.NewDecoder(data) var o CommandResponse diff --git a/model/command_response_test.go b/model/command_response_test.go index df478ff2c..19be796b8 100644 --- a/model/command_response_test.go +++ b/model/command_response_test.go @@ -18,6 +18,30 @@ func TestCommandResponseJson(t *testing.T) { } } +func TestCommandResponseFromHTTPBody(t *testing.T) { + for _, test := range []struct { + ContentType string + Body string + ExpectedText string + }{ + {"", "foo", "foo"}, + {"text/plain", "foo", "foo"}, + {"application/json", `{"text": "foo"}`, "foo"}, + } { + response := CommandResponseFromHTTPBody(test.ContentType, strings.NewReader(test.Body)) + if response.Text != test.ExpectedText { + t.Fatal() + } + } +} + +func TestCommandResponseFromPlainText(t *testing.T) { + response := CommandResponseFromPlainText("foo") + if response.Text != "foo" { + t.Fatal("text should be foo") + } +} + func TestCommandResponseFromJson(t *testing.T) { json := `{ "response_type": "ephemeral", diff --git a/model/command_webhook.go b/model/command_webhook.go new file mode 100644 index 000000000..0b00e00b6 --- /dev/null +++ b/model/command_webhook.go @@ -0,0 +1,65 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "net/http" +) + +type CommandWebhook struct { + Id string + CreateAt int64 + CommandId string + UserId string + ChannelId string + RootId string + ParentId string + UseCount int +} + +const ( + COMMAND_WEBHOOK_LIFETIME = 1000 * 60 * 30 +) + +func (o *CommandWebhook) PreSave() { + if o.Id == "" { + o.Id = NewId() + } + + if o.CreateAt == 0 { + o.CreateAt = GetMillis() + } +} + +func (o *CommandWebhook) IsValid() *AppError { + if len(o.Id) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.id.app_error", nil, "", http.StatusBadRequest) + } + + if o.CreateAt == 0 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) + } + + if len(o.CommandId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.command_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.UserId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.user_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.ChannelId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.channel_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.RootId) != 0 && len(o.RootId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.root_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.ParentId) != 0 && len(o.ParentId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.parent_id.app_error", nil, "", http.StatusBadRequest) + } + + return nil +} diff --git a/model/command_webhook_test.go b/model/command_webhook_test.go new file mode 100644 index 000000000..629bbdaa7 --- /dev/null +++ b/model/command_webhook_test.go @@ -0,0 +1,54 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "testing" +) + +func TestCommandWebhookPreSave(t *testing.T) { + h := CommandWebhook{} + h.PreSave() + if len(h.Id) != 26 { + t.Fatal("Id should be generated") + } + if h.CreateAt == 0 { + t.Fatal("CreateAt should be set") + } +} + +func TestCommandWebhookIsValid(t *testing.T) { + h := CommandWebhook{} + h.Id = NewId() + h.CreateAt = GetMillis() + h.CommandId = NewId() + h.UserId = NewId() + h.ChannelId = NewId() + + for _, test := range []struct { + Transform func() + ExpectedError string + }{ + {func() {}, ""}, + {func() { h.Id = "asd" }, "model.command_hook.id.app_error"}, + {func() { h.CreateAt = 0 }, "model.command_hook.create_at.app_error"}, + {func() { h.CommandId = "asd" }, "model.command_hook.command_id.app_error"}, + {func() { h.UserId = "asd" }, "model.command_hook.user_id.app_error"}, + {func() { h.ChannelId = "asd" }, "model.command_hook.channel_id.app_error"}, + {func() { h.RootId = "asd" }, "model.command_hook.root_id.app_error"}, + {func() { h.RootId = NewId() }, ""}, + {func() { h.ParentId = "asd" }, "model.command_hook.parent_id.app_error"}, + {func() { h.ParentId = NewId() }, ""}, + } { + tmp := h + test.Transform() + err := h.IsValid() + if test.ExpectedError == "" && err != nil { + t.Fatal("hook should be valid") + } else if test.ExpectedError != "" && test.ExpectedError != err.Id { + t.Fatal("expected " + test.ExpectedError + " error") + } + h = tmp + } +} -- cgit v1.2.3-1-g7c22