From e7b25f4cd8b7d87b99153fd4a901d3f9f92d7b0d Mon Sep 17 00:00:00 2001 From: Alexander Smaga Date: Mon, 17 Oct 2016 15:12:56 +0300 Subject: GH-4187 Create direct channel during incoming webhook if not exists (#4206) --- api/channel.go | 23 +++-------------------- api/webhook.go | 15 +++++++++++++-- api/webhook_test.go | 2 -- store/sql_channel_store.go | 23 +++++++++++++++++++++++ store/sql_channel_store_test.go | 27 +++++++++++++++++++++++++++ store/store.go | 1 + 6 files changed, 67 insertions(+), 24 deletions(-) diff --git a/api/channel.go b/api/channel.go index 538c2d497..f40c979ca 100644 --- a/api/channel.go +++ b/api/channel.go @@ -137,36 +137,19 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) { func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { uc := Srv.Store.User().Get(otherUserId) - channel := new(model.Channel) - - channel.DisplayName = "" - channel.Name = model.GetDMNameFromIds(otherUserId, userId) - - channel.Header = "" - channel.Type = model.CHANNEL_DIRECT - if uresult := <-uc; uresult.Err != nil { return nil, model.NewLocAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId) } - cm1 := &model.ChannelMember{ - UserId: userId, - NotifyProps: model.GetDefaultChannelNotifyProps(), - Roles: model.ROLE_CHANNEL_USER.Id, - } - cm2 := &model.ChannelMember{ - UserId: otherUserId, - NotifyProps: model.GetDefaultChannelNotifyProps(), - Roles: model.ROLE_CHANNEL_USER.Id, - } - - if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil { + if result := <-Srv.Store.Channel().CreateDirectChannel(userId, otherUserId); result.Err != nil { if result.Err.Id == store.CHANNEL_EXISTS_ERROR { return result.Data.(*model.Channel), nil } else { return nil, result.Err } } else { + channel := result.Data.(*model.Channel) + message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil) message.Add("teammate_id", otherUserId) go Publish(message) diff --git a/api/webhook.go b/api/webhook.go index 2995a4a9d..2daac03f2 100644 --- a/api/webhook.go +++ b/api/webhook.go @@ -412,6 +412,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { var channel *model.Channel var cchan store.StoreChannel + var directUserId string if len(channelName) != 0 { if channelName[0] == '@' { @@ -419,7 +420,8 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message) return } else { - channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId) + directUserId = result.Data.(*model.User).Id + channelName = model.GetDMNameFromIds(directUserId, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] @@ -433,7 +435,16 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { overrideUsername := parsedRequest.Username overrideIconUrl := parsedRequest.IconURL - if result := <-cchan; result.Err != nil { + result := <-cchan + if result.Err != nil && result.Err.Id == store.MISSING_CHANNEL_ERROR && directUserId != "" { + newChanResult := <-Srv.Store.Channel().CreateDirectChannel(directUserId, hook.UserId) + if newChanResult.Err != nil { + c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+newChanResult.Err.Message) + return + } else { + channel = newChanResult.Data.(*model.Channel) + } + } else if result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message) return } else { diff --git a/api/webhook_test.go b/api/webhook_test.go index b3fa04d88..ae3b48032 100644 --- a/api/webhook_test.go +++ b/api/webhook_test.go @@ -597,8 +597,6 @@ func TestIncomingWebhooks(t *testing.T) { t.Fatal(err) } - Client.Must(Client.CreateDirectChannel(user2.Id)) - if _, err := Client.DoPost(url, fmt.Sprintf("{\"text\":\"this is a test\", \"channel\":\"@%s\"}", user2.Username), "application/json"); err != nil { t.Fatal(err) } diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go index 07c037075..eb150a63c 100644 --- a/store/sql_channel_store.go +++ b/store/sql_channel_store.go @@ -83,6 +83,29 @@ func (s SqlChannelStore) Save(channel *model.Channel) StoreChannel { return storeChannel } +func (s SqlChannelStore) CreateDirectChannel(userId string, otherUserId string) StoreChannel { + channel := new(model.Channel) + + channel.DisplayName = "" + channel.Name = model.GetDMNameFromIds(otherUserId, userId) + + channel.Header = "" + channel.Type = model.CHANNEL_DIRECT + + cm1 := &model.ChannelMember{ + UserId: userId, + NotifyProps: model.GetDefaultChannelNotifyProps(), + Roles: model.ROLE_CHANNEL_USER.Id, + } + cm2 := &model.ChannelMember{ + UserId: otherUserId, + NotifyProps: model.GetDefaultChannelNotifyProps(), + Roles: model.ROLE_CHANNEL_USER.Id, + } + + return s.SaveDirectChannel(channel, cm1, cm2) +} + func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) StoreChannel { storeChannel := make(StoreChannel, 1) diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go index 0bd059e5f..19db3d003 100644 --- a/store/sql_channel_store_test.go +++ b/store/sql_channel_store_test.go @@ -94,7 +94,34 @@ func TestChannelStoreSaveDirectChannel(t *testing.T) { if err := (<-store.Channel().SaveDirectChannel(&o1, &m1, &m2)).Err; err == nil { t.Fatal("Should not be able to save non-direct channel") } +} + +func TestChannelStoreCreateDirectChannel(t *testing.T) { + Setup() + u1 := &model.User{} + u1.Email = model.NewId() + u1.Nickname = model.NewId() + Must(store.User().Save(u1)) + Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Nickname = model.NewId() + Must(store.User().Save(u2)) + Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) + + res := <-store.Channel().CreateDirectChannel(u1.Id, u2.Id) + if res.Err != nil { + t.Fatal("couldn't create direct channel", res.Err) + } + + c1 := res.Data.(*model.Channel) + + members := (<-store.Channel().GetMembers(c1.Id)).Data.([]model.ChannelMember) + if len(members) != 2 { + t.Fatal("should have saved 2 members") + } } func TestChannelStoreUpdate(t *testing.T) { diff --git a/store/store.go b/store/store.go index c01b6d8bc..7474d3afb 100644 --- a/store/store.go +++ b/store/store.go @@ -75,6 +75,7 @@ type TeamStore interface { type ChannelStore interface { Save(channel *model.Channel) StoreChannel + CreateDirectChannel(userId string, otherUserId string) StoreChannel SaveDirectChannel(channel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) StoreChannel Update(channel *model.Channel) StoreChannel Get(id string) StoreChannel -- cgit v1.2.3-1-g7c22