From a0566b63d07872e5128152aa10bad7cdae589df7 Mon Sep 17 00:00:00 2001 From: Saturnino Abril Date: Sat, 25 Mar 2017 05:12:07 +0900 Subject: [PATCH] updated enpoint as /teams/{team_id}/channels/ids --- api4/channel.go | 58 +++++----- api4/channel_test.go | 113 ++++++++++--------- app/channel.go | 4 +- model/client4.go | 22 ++-- store/sql_channel_store.go | 89 ++++++++------- store/sql_channel_store_test.go | 185 ++++++++++++++------------------ store/store.go | 2 +- 7 files changed, 241 insertions(+), 232 deletions(-) diff --git a/api4/channel.go b/api4/channel.go index e5544d025549d..e7ecfcd5ec411 100644 --- a/api4/channel.go +++ b/api4/channel.go @@ -18,9 +18,9 @@ func InitChannel() { BaseRoutes.Channels.Handle("", ApiSessionRequired(createChannel)).Methods("POST") BaseRoutes.Channels.Handle("/direct", ApiSessionRequired(createDirectChannel)).Methods("POST") BaseRoutes.Channels.Handle("/members/{user_id:[A-Za-z0-9]+}/view", ApiSessionRequired(viewChannel)).Methods("POST") - BaseRoutes.Channels.Handle("/ids", ApiSessionRequired(getChannelsByIds)).Methods("POST") - BaseRoutes.Team.Handle("/channels", ApiSessionRequired(getPublicChannelsForTeam)).Methods("GET") + BaseRoutes.ChannelsForTeam.Handle("", ApiSessionRequired(getPublicChannelsForTeam)).Methods("GET") + BaseRoutes.ChannelsForTeam.Handle("/ids", ApiSessionRequired(getPublicChannelsByIdsForTeam)).Methods("POST") BaseRoutes.Channel.Handle("", ApiSessionRequired(getChannel)).Methods("GET") BaseRoutes.Channel.Handle("", ApiSessionRequired(updateChannel)).Methods("PUT") @@ -289,6 +289,38 @@ func getPublicChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request } } +func getPublicChannelsByIdsForTeam(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireTeamId() + if c.Err != nil { + return + } + + channelIds := model.ArrayFromJson(r.Body) + if len(channelIds) == 0 { + c.SetInvalidParam("channel_ids") + return + } + + for _, cid := range channelIds { + if len(cid) != 26 { + c.SetInvalidParam("channel_id") + return + } + } + + if !app.SessionHasPermissionToTeam(c.Session, c.Params.TeamId, model.PERMISSION_VIEW_TEAM) { + c.SetPermissionError(model.PERMISSION_VIEW_TEAM) + return + } + + if channels, err := app.GetPublicChannelsByIdsForTeam(c.Params.TeamId, channelIds); err != nil { + c.Err = err + return + } else { + w.Write([]byte(channels.ToJson())) + } +} + func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireChannelId() if c.Err != nil { @@ -487,28 +519,6 @@ func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) { ReturnStatusOK(w) } -func getChannelsByIds(c *Context, w http.ResponseWriter, r *http.Request) { - channelIds := model.ArrayFromJson(r.Body) - if len(channelIds) == 0 { - c.SetInvalidParam("channel_ids") - return - } - - for _, cid := range channelIds { - if len(cid) != 26 { - c.SetInvalidParam("channel_id") - return - } - } - - if channels, err := app.GetChannelsByIds(channelIds, c.Session.UserId); err != nil { - c.Err = err - return - } else { - w.Write([]byte(channels.ToJson())) - } -} - func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireChannelId().RequireUserId() if c.Err != nil { diff --git a/api4/channel_test.go b/api4/channel_test.go index 1e20419c67491..f65a4d893d464 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -439,6 +439,68 @@ func TestGetPublicChannelsForTeam(t *testing.T) { CheckNoError(t, resp) } +func TestGetPublicChannelsByIdsForTeam(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + teamId := th.BasicTeam.Id + input := []string{th.BasicChannel.Id} + output := []string{th.BasicChannel.DisplayName} + + channels, resp := Client.GetPublicChannelsByIdsForTeam(teamId, input) + CheckNoError(t, resp) + + if len(*channels) != 1 { + t.Fatal("should return 1 channel") + } + + if (*channels)[0].DisplayName != output[0] { + t.Fatal("missing channel") + } + + input = append(input, GenerateTestId()) + input = append(input, th.BasicChannel2.Id) + input = append(input, th.BasicPrivateChannel.Id) + output = append(output, th.BasicChannel2.DisplayName) + sort.Strings(output) + + channels, resp = Client.GetPublicChannelsByIdsForTeam(teamId, input) + CheckNoError(t, resp) + + if len(*channels) != 2 { + t.Fatal("should return 2 channels") + } + + for i, c := range *channels { + if c.DisplayName != output[i] { + t.Fatal("missing channel") + } + } + + _, resp = Client.GetPublicChannelsByIdsForTeam(GenerateTestId(), input) + CheckForbiddenStatus(t, resp) + + _, resp = Client.GetPublicChannelsByIdsForTeam(teamId, []string{}) + CheckBadRequestStatus(t, resp) + + _, resp = Client.GetPublicChannelsByIdsForTeam(teamId, []string{"junk"}) + CheckBadRequestStatus(t, resp) + + _, resp = Client.GetPublicChannelsByIdsForTeam(teamId, []string{GenerateTestId()}) + CheckNotFoundStatus(t, resp) + + _, resp = Client.GetPublicChannelsByIdsForTeam(teamId, []string{th.BasicPrivateChannel.Id}) + CheckNotFoundStatus(t, resp) + + Client.Logout() + + _, resp = Client.GetPublicChannelsByIdsForTeam(teamId, input) + CheckUnauthorizedStatus(t, resp) + + _, resp = th.SystemAdminClient.GetPublicChannelsByIdsForTeam(teamId, input) + CheckNoError(t, resp) +} + func TestDeleteChannel(t *testing.T) { th := Setup().InitBasic().InitSystemAdmin() defer TearDown() @@ -1023,57 +1085,6 @@ func TestViewChannel(t *testing.T) { CheckNoError(t, resp) } -func TestGetChannelsByIds(t *testing.T) { - th := Setup().InitBasic() - defer TearDown() - Client := th.Client - input := []string{th.BasicChannel.Id} - output := []string{th.BasicChannel.DisplayName} - - channels, resp := Client.GetChannelsByIds(input) - CheckNoError(t, resp) - - if len(*channels) != 1 { - t.Fatal("should return 1 channel") - } - - if (*channels)[0].DisplayName != output[0] { - t.Fatal("missing channel") - } - - input = append(input, GenerateTestId()) - input = append(input, th.BasicChannel2.Id) - output = append(output, th.BasicChannel2.DisplayName) - sort.Strings(output) - - channels, resp = Client.GetChannelsByIds(input) - CheckNoError(t, resp) - - if len(*channels) != 2 { - t.Fatal("should return 2 channels") - } - - for i, c := range *channels { - if c.DisplayName != output[i] { - t.Fatal("missing channel") - } - } - - _, resp = Client.GetChannelsByIds([]string{}) - CheckBadRequestStatus(t, resp) - - _, resp = Client.GetChannelsByIds([]string{"junk"}) - CheckBadRequestStatus(t, resp) - - _, resp = Client.GetChannelsByIds([]string{GenerateTestId()}) - CheckNotFoundStatus(t, resp) - - Client.Logout() - - _, resp = Client.GetChannelsByIds(input) - CheckUnauthorizedStatus(t, resp) -} - func TestGetChannelUnread(t *testing.T) { th := Setup().InitBasic().InitSystemAdmin() defer TearDown() diff --git a/app/channel.go b/app/channel.go index 8edefc3a9d9d1..34c27d9f75e89 100644 --- a/app/channel.go +++ b/app/channel.go @@ -671,8 +671,8 @@ func GetChannelsUserNotIn(teamId string, userId string, offset int, limit int) ( } } -func GetChannelsByIds(channelIds []string, userId string) (*model.ChannelList, *model.AppError) { - if result := <-Srv.Store.Channel().GetChannelsByIds(channelIds, userId); result.Err != nil { +func GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) (*model.ChannelList, *model.AppError) { + if result := <-Srv.Store.Channel().GetPublicChannelsByIdsForTeam(teamId, channelIds); result.Err != nil { return nil, result.Err } else { return result.Data.(*model.ChannelList), nil diff --git a/model/client4.go b/model/client4.go index 633ef2dc0314e..6d8d64e6092dd 100644 --- a/model/client4.go +++ b/model/client4.go @@ -916,7 +916,7 @@ func (c *Client4) GetChannelStats(channelId string, etag string) (*ChannelStats, } } -// GetPublicChannelsForTeam returns a channel based on the provided team id string. +// GetPublicChannelsForTeam returns a list of channels based on the provided team id string. func (c *Client4) GetPublicChannelsForTeam(teamId string, page int, perPage int, etag string) (*ChannelList, *Response) { query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) if r, err := c.DoApiGet(c.GetPublicChannelsForTeamRoute(teamId)+query, etag); err != nil { @@ -927,6 +927,16 @@ func (c *Client4) GetPublicChannelsForTeam(teamId string, page int, perPage int, } } +// GetPublicChannelsByIdsForTeam returns a list of channels based on provided team id string +func (c *Client4) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) (*ChannelList, *Response) { + if r, err := c.DoApiPost(c.GetPublicChannelsForTeamRoute(teamId)+"/ids", ArrayToJson(channelIds)); err != nil { + return nil, &Response{StatusCode: r.StatusCode, Error: err} + } else { + defer closeBody(r) + return ChannelListFromJson(r.Body), BuildResponse(r) + } +} + // DeleteChannel deletes channel based on the provided channel id string. func (c *Client4) DeleteChannel(channelId string) (bool, *Response) { if r, err := c.DoApiDelete(c.GetChannelRoute(channelId)); err != nil { @@ -1010,16 +1020,6 @@ func (c *Client4) ViewChannel(userId string, view *ChannelView) (bool, *Response } } -// GetChannelsByIds gets a list of channels that the user is member of -func (c *Client4) GetChannelsByIds(channelIds []string) (*ChannelList, *Response) { - if r, err := c.DoApiPost(c.GetChannelsRoute()+"/ids", ArrayToJson(channelIds)); err != nil { - return nil, &Response{StatusCode: r.StatusCode, Error: err} - } else { - defer closeBody(r) - return ChannelListFromJson(r.Body), BuildResponse(r) - } -} - // GetChannelUnread will return a ChannelUnread object that contains the number of // unread messages and mentions for a user. func (c *Client4) GetChannelUnread(channelId, userId string) (*ChannelUnread, *Response) { diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go index 45fedf7498901..309337e50cf5e 100644 --- a/store/sql_channel_store.go +++ b/store/sql_channel_store.go @@ -541,45 +541,6 @@ func (s SqlChannelStore) GetChannels(teamId string, userId string) StoreChannel return storeChannel } -func (s SqlChannelStore) GetChannelsByIds(channelIds []string, userId string) StoreChannel { - storeChannel := make(StoreChannel, 1) - - go func() { - result := StoreResult{} - - props := make(map[string]interface{}) - props["userId"] = userId - - idQuery := "" - - for index, channelId := range channelIds { - if len(idQuery) > 0 { - idQuery += ", " - } - - props["channelId"+strconv.Itoa(index)] = channelId - idQuery += ":channelId" + strconv.Itoa(index) - } - - data := &model.ChannelList{} - _, err := s.GetReplica().Select(data, "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :userId AND DeleteAt = 0 AND ChannelId IN ("+idQuery+") ORDER BY DisplayName", props) - - if err != nil { - result.Err = model.NewLocAppError("SqlChannelStore.GetChannelsByIds", "store.sql_channel.get_channels_by_ids.get.app_error", nil, err.Error()) - } - - if len(*data) == 0 { - result.Err = model.NewAppError("SqlChannelStore.GetChannelsByIds", "store.sql_channel.get_channels_by_ids.not_found.app_error", nil, "", http.StatusNotFound) - } - - result.Data = data - storeChannel <- result - close(storeChannel) - }() - - return storeChannel -} - func (s SqlChannelStore) GetMoreChannels(teamId string, userId string, offset int, limit int) StoreChannel { storeChannel := make(StoreChannel, 1) @@ -658,6 +619,56 @@ func (s SqlChannelStore) GetPublicChannelsForTeam(teamId string, offset int, lim return storeChannel } +func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) StoreChannel { + storeChannel := make(StoreChannel, 1) + + go func() { + result := StoreResult{} + + props := make(map[string]interface{}) + props["teamId"] = teamId + + idQuery := "" + + for index, channelId := range channelIds { + if len(idQuery) > 0 { + idQuery += ", " + } + + props["channelId"+strconv.Itoa(index)] = channelId + idQuery += ":channelId" + strconv.Itoa(index) + } + + data := &model.ChannelList{} + _, err := s.GetReplica().Select(data, + `SELECT + * + FROM + Channels + WHERE + TeamId = :teamId + AND Type = 'O' + AND DeleteAt = 0 + AND Id IN (`+idQuery+`) + ORDER BY DisplayName`, + props) + + if err != nil { + result.Err = model.NewLocAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.get.app_error", nil, err.Error()) + } + + if len(*data) == 0 { + result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.not_found.app_error", nil, "", http.StatusNotFound) + } + + result.Data = data + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + type channelIdWithCountAndUpdateAt struct { Id string TotalMsgCount int64 diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go index 1a1b58131a333..3cc6f3bc4ec93 100644 --- a/store/sql_channel_store_test.go +++ b/store/sql_channel_store_test.go @@ -732,110 +732,6 @@ func TestChannelStoreGetChannels(t *testing.T) { store.Channel().InvalidateAllChannelMembersForUser(m1.UserId) } -func TestChannelStoreGetChannelsByIds(t *testing.T) { - Setup() - - co1 := model.Channel{} - co1.TeamId = model.NewId() - co1.DisplayName = "Channel1" - co1.Name = "a" + model.NewId() + "b" - co1.Type = model.CHANNEL_OPEN - Must(store.Channel().Save(&co1)) - - co2 := model.Channel{} - co2.TeamId = model.NewId() - co2.DisplayName = "Channel2" - co2.Name = "a" + model.NewId() + "b" - co2.Type = model.CHANNEL_OPEN - Must(store.Channel().Save(&co2)) - - cp3 := model.Channel{} - cp3.TeamId = model.NewId() - cp3.DisplayName = "Channel3" - cp3.Name = "a" + model.NewId() + "b" - cp3.Type = model.CHANNEL_PRIVATE - Must(store.Channel().Save(&cp3)) - - cm1 := model.ChannelMember{} - cm1.ChannelId = co1.Id - cm1.UserId = model.NewId() - cm1.NotifyProps = model.GetDefaultChannelNotifyProps() - Must(store.Channel().SaveMember(&cm1)) - - cm2 := model.ChannelMember{} - cm2.ChannelId = co1.Id - cm2.UserId = model.NewId() - cm2.NotifyProps = model.GetDefaultChannelNotifyProps() - Must(store.Channel().SaveMember(&cm2)) - - cm2.ChannelId = co2.Id - Must(store.Channel().SaveMember(&cm2)) - - cm2.ChannelId = cp3.Id - Must(store.Channel().SaveMember(&cm2)) - - cids := []string{co1.Id} - cresult := <-store.Channel().GetChannelsByIds(cids, cm1.UserId) - list := cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("should return 1 channel") - } - - if (*list)[0].Id != co1.Id { - t.Fatal("missing channel") - } - - cids = append(cids, co2.Id) - cresult = <-store.Channel().GetChannelsByIds(cids, cm1.UserId) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("should return 1 channel") - } - - cresult = <-store.Channel().GetChannelsByIds(cids, cm2.UserId) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 2 { - t.Fatal("should return 2 channels") - } - - cids = append(cids, cp3.Id) - cresult = <-store.Channel().GetChannelsByIds(cids, cm2.UserId) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 3 { - t.Fatal("should return 3 channels") - } - - for i, c := range *list { - if c.Id != cids[i] { - t.Fatal("missing channel") - } - } - - cids = append(cids, model.NewId()) - cresult = <-store.Channel().GetChannelsByIds(cids, cm2.UserId) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 3 { - t.Fatal("should return 3 channels") - } - - cids = cids[:0] - cids = append(cids, model.NewId()) - cresult = <-store.Channel().GetChannelsByIds(cids, cm2.UserId) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 0 { - t.Fatal("should not return a channel") - } - - store.Channel().InvalidateAllChannelMembersForUser(cm1.UserId) - store.Channel().InvalidateAllChannelMembersForUser(cm2.UserId) -} - func TestChannelStoreGetMoreChannels(t *testing.T) { Setup() @@ -1038,6 +934,87 @@ func TestChannelStoreGetPublicChannelsForTeam(t *testing.T) { } } +func TestChannelStoreGetPublicChannelsByIdsForTeam(t *testing.T) { + Setup() + + teamId1 := model.NewId() + + oc1 := model.Channel{} + oc1.TeamId = teamId1 + oc1.DisplayName = "OpenChannel1Team1" + oc1.Name = "a" + model.NewId() + "b" + oc1.Type = model.CHANNEL_OPEN + Must(store.Channel().Save(&oc1)) + + oc2 := model.Channel{} + oc2.TeamId = model.NewId() + oc2.DisplayName = "OpenChannel2TeamOther" + oc2.Name = "a" + model.NewId() + "b" + oc2.Type = model.CHANNEL_OPEN + Must(store.Channel().Save(&oc2)) + + pc3 := model.Channel{} + pc3.TeamId = teamId1 + pc3.DisplayName = "PrivateChannel3Team1" + pc3.Name = "a" + model.NewId() + "b" + pc3.Type = model.CHANNEL_PRIVATE + Must(store.Channel().Save(&pc3)) + + cids := []string{oc1.Id} + cresult := <-store.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list := cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("should return 1 channel") + } + + if (*list)[0].Id != oc1.Id { + t.Fatal("missing channel") + } + + cids = append(cids, oc2.Id) + cids = append(cids, model.NewId()) + cids = append(cids, pc3.Id) + cresult = <-store.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("should return 1 channel") + } + + oc4 := model.Channel{} + oc4.TeamId = teamId1 + oc4.DisplayName = "OpenChannel4Team1" + oc4.Name = "a" + model.NewId() + "b" + oc4.Type = model.CHANNEL_OPEN + Must(store.Channel().Save(&oc4)) + + cids = append(cids, oc4.Id) + cresult = <-store.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 2 { + t.Fatal("should return 2 channels") + } + + if (*list)[0].Id != oc1.Id { + t.Fatal("missing channel") + } + + if (*list)[1].Id != oc4.Id { + t.Fatal("missing channel") + } + + cids = cids[:0] + cids = append(cids, model.NewId()) + cresult = <-store.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 0 { + t.Fatal("should not return a channel") + } +} + func TestChannelStoreGetChannelCounts(t *testing.T) { Setup() diff --git a/store/store.go b/store/store.go index 2479042c22866..528b26a3f9307 100644 --- a/store/store.go +++ b/store/store.go @@ -101,9 +101,9 @@ type ChannelStore interface { GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) StoreChannel GetDeletedByName(team_id string, name string) StoreChannel GetChannels(teamId string, userId string) StoreChannel - GetChannelsByIds(channelIds []string, userId string) StoreChannel GetMoreChannels(teamId string, userId string, offset int, limit int) StoreChannel GetPublicChannelsForTeam(teamId string, offset int, limit int) StoreChannel + GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) StoreChannel GetChannelCounts(teamId string, userId string) StoreChannel GetTeamChannels(teamId string) StoreChannel GetAll(teamId string) StoreChannel