diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/api.go | 1 | ||||
-rw-r--r-- | api/channel.go | 73 | ||||
-rw-r--r-- | api/channel_test.go | 207 | ||||
-rw-r--r-- | api/command_join.go | 23 | ||||
-rw-r--r-- | api/deprecated.go | 39 | ||||
-rw-r--r-- | api/deprecated_test.go | 43 | ||||
-rw-r--r-- | api/user.go | 9 |
7 files changed, 361 insertions, 34 deletions
diff --git a/api/api.go b/api/api.go index eea70c9b5..3af23b9e0 100644 --- a/api/api.go +++ b/api/api.go @@ -103,6 +103,7 @@ func InitApi() { InitEmoji() InitStatus() InitWebrtc() + InitDeprecated() // 404 on any api route before web.go has a chance to serve it Srv.Router.Handle("/api/{anything:.*}", http.HandlerFunc(Handle404)) diff --git a/api/channel.go b/api/channel.go index 9ec556fe6..0ffe9a668 100644 --- a/api/channel.go +++ b/api/channel.go @@ -6,6 +6,7 @@ package api import ( "fmt" "net/http" + "strconv" "strings" l4g "github.com/alecthomas/log4go" @@ -19,7 +20,8 @@ func InitChannel() { l4g.Debug(utils.T("api.channel.init.debug")) BaseRoutes.Channels.Handle("/", ApiUserRequired(getChannels)).Methods("GET") - BaseRoutes.Channels.Handle("/more", ApiUserRequired(getMoreChannels)).Methods("GET") + BaseRoutes.Channels.Handle("/more/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequired(getMoreChannelsPage)).Methods("GET") + BaseRoutes.Channels.Handle("/more/search", ApiUserRequired(searchMoreChannels)).Methods("POST") BaseRoutes.Channels.Handle("/counts", ApiUserRequired(getChannelCounts)).Methods("GET") BaseRoutes.Channels.Handle("/members", ApiUserRequired(getMyChannelMembers)).Methods("GET") BaseRoutes.Channels.Handle("/create", ApiUserRequired(createChannel)).Methods("POST") @@ -28,6 +30,7 @@ func InitChannel() { BaseRoutes.Channels.Handle("/update_header", ApiUserRequired(updateChannelHeader)).Methods("POST") BaseRoutes.Channels.Handle("/update_purpose", ApiUserRequired(updateChannelPurpose)).Methods("POST") BaseRoutes.Channels.Handle("/update_notify_props", ApiUserRequired(updateNotifyProps)).Methods("POST") + BaseRoutes.Channels.Handle("/autocomplete", ApiUserRequired(autocompleteChannels)).Methods("GET") BaseRoutes.NeedChannelName.Handle("/join", ApiUserRequired(join)).Methods("POST") @@ -41,6 +44,7 @@ func InitChannel() { BaseRoutes.NeedChannel.Handle("/remove", ApiUserRequired(removeMember)).Methods("POST") BaseRoutes.NeedChannel.Handle("/update_last_viewed_at", ApiUserRequired(updateLastViewedAt)).Methods("POST") BaseRoutes.NeedChannel.Handle("/set_last_viewed_at", ApiUserRequired(setLastViewedAt)).Methods("POST") + } func createChannel(c *Context, w http.ResponseWriter, r *http.Request) { @@ -416,18 +420,29 @@ func getChannels(c *Context, w http.ResponseWriter, r *http.Request) { } } -func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) { +func getMoreChannelsPage(c *Context, w http.ResponseWriter, r *http.Request) { + params := mux.Vars(r) + + offset, err := strconv.Atoi(params["offset"]) + if err != nil { + c.SetInvalidParam("getProfiles", "offset") + return + } + + limit, err := strconv.Atoi(params["limit"]) + if err != nil { + c.SetInvalidParam("getProfiles", "limit") + return + } // user is already in the team if !HasPermissionToTeamContext(c, c.TeamId, model.PERMISSION_LIST_TEAM_CHANNELS) { return } - if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId); result.Err != nil { + if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId, offset, limit); result.Err != nil { c.Err = result.Err return - } else if HandleEtag(result.Data.(*model.ChannelList).Etag(), w, r) { - return } else { data := result.Data.(*model.ChannelList) w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag()) @@ -1182,3 +1197,51 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) { } } + +func searchMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) { + props := model.ChannelSearchFromJson(r.Body) + if props == nil { + c.SetInvalidParam("searchMoreChannels", "") + return + } + + if c.Session.GetTeamByTeamId(c.TeamId) == nil { + if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) { + return + } + } + + if len(props.Term) == 0 { + c.SetInvalidParam("searchMoreChannels", "term") + return + } + + if result := <-Srv.Store.Channel().SearchMore(c.Session.UserId, c.TeamId, props.Term); result.Err != nil { + c.Err = result.Err + return + } else { + channels := result.Data.(*model.ChannelList) + w.Write([]byte(channels.ToJson())) + } +} + +func autocompleteChannels(c *Context, w http.ResponseWriter, r *http.Request) { + term := r.URL.Query().Get("term") + + if c.Session.GetTeamByTeamId(c.TeamId) == nil { + if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) { + return + } + } + + var channels *model.ChannelList + + if result := <-Srv.Store.Channel().SearchInTeam(c.TeamId, term); result.Err != nil { + c.Err = result.Err + return + } else { + channels = result.Data.(*model.ChannelList) + } + + w.Write([]byte(channels.ToJson())) +} diff --git a/api/channel_test.go b/api/channel_test.go index 4b0ce9509..611fa9339 100644 --- a/api/channel_test.go +++ b/api/channel_test.go @@ -705,7 +705,7 @@ func TestGetChannel(t *testing.T) { } } -func TestGetMoreChannel(t *testing.T) { +func TestGetMoreChannelsPage(t *testing.T) { th := Setup().InitBasic() Client := th.BasicClient team := th.BasicTeam @@ -713,28 +713,64 @@ func TestGetMoreChannel(t *testing.T) { channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) - channel2 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel2 := &model.Channel{DisplayName: "B Test API Name", Name: "b" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) + channel3 := &model.Channel{DisplayName: "C Test API Name", Name: "c" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id} + channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel) + th.LoginBasic2() - rget := Client.Must(Client.GetMoreChannels("")) - channels := rget.Data.(*model.ChannelList) + if r, err := Client.GetMoreChannelsPage(0, 100); err != nil { + t.Fatal(err) + } else { + channels := r.Data.(*model.ChannelList) - if (*channels)[0].DisplayName != channel1.DisplayName { - t.Fatal("full name didn't match") + // 1 for BasicChannel, 2 for open channels created above + if len(*channels) != 3 { + t.Fatal("wrong length") + } + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } + + if (*channels)[1].DisplayName != channel2.DisplayName { + t.Fatal("full name didn't match") + } } - if (*channels)[1].DisplayName != channel2.DisplayName { - t.Fatal("full name didn't match") + if r, err := Client.GetMoreChannelsPage(0, 1); err != nil { + t.Fatal(err) + } else { + channels := r.Data.(*model.ChannelList) + + if len(*channels) != 1 { + t.Fatal("wrong length") + } + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } } - // test etag caching - if cache_result, err := Client.GetMoreChannels(rget.Etag); err != nil { + if r, err := Client.GetMoreChannelsPage(1, 1); err != nil { t.Fatal(err) - } else if cache_result.Data.(*model.ChannelList) != nil { - t.Log(cache_result.Data) - t.Fatal("cache should be empty") + } else { + channels := r.Data.(*model.ChannelList) + + if len(*channels) != 1 { + t.Fatal("wrong length") + } + + if (*channels)[0].DisplayName != channel2.DisplayName { + t.Fatal("full name didn't match") + } + } + + Client.SetTeamId("junk") + if _, err := Client.GetMoreChannelsPage(0, 1); err == nil { + t.Fatal("should have failed - bad team id") } } @@ -1448,3 +1484,148 @@ func TestGetChannelMember(t *testing.T) { t.Fatal("should have failed - bad channel and user id") } } + +func TestSearchMoreChannels(t *testing.T) { + th := Setup().InitBasic() + Client := th.BasicClient + team := th.BasicTeam + + channel1 := &model.Channel{DisplayName: "TestAPINameA", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) + + channel2 := &model.Channel{DisplayName: "TestAPINameB", Name: "b" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) + + th.LoginBasic2() + + if result, err := Client.SearchMoreChannels(model.ChannelSearch{Term: "TestAPIName"}); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } + + if (*channels)[1].DisplayName != channel2.DisplayName { + t.Fatal("full name didn't match") + } + } + + if result, err := Client.SearchMoreChannels(model.ChannelSearch{Term: "TestAPINameA"}); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } + } + + if result, err := Client.SearchMoreChannels(model.ChannelSearch{Term: "TestAPINameB"}); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if (*channels)[0].DisplayName != channel2.DisplayName { + t.Fatal("full name didn't match") + } + } + + if result, err := Client.SearchMoreChannels(model.ChannelSearch{Term: channel1.Name}); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } + } + + if _, err := Client.SearchMoreChannels(model.ChannelSearch{Term: ""}); err == nil { + t.Fatal("should have errored - empty term") + } + + if result, err := Client.SearchMoreChannels(model.ChannelSearch{Term: "blargh"}); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if len(*channels) != 0 { + t.Fatal("should have no channels") + } + } + + Client.SetTeamId("junk") + if _, err := Client.SearchMoreChannels(model.ChannelSearch{Term: "blargh"}); err == nil { + t.Fatal("should have errored - bad team id") + } +} + +func TestAutocompleteChannels(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + Client := th.BasicClient + team := th.BasicTeam + + channel1 := &model.Channel{DisplayName: "TestAPINameA", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) + + channel2 := &model.Channel{DisplayName: "TestAPINameB", Name: "b" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) + + channel3 := &model.Channel{DisplayName: "BadChannelC", Name: "c" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: model.NewId()} + channel3 = th.SystemAdminClient.Must(th.SystemAdminClient.CreateChannel(channel3)).Data.(*model.Channel) + + channel4 := &model.Channel{DisplayName: "BadChannelD", Name: "d" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id} + channel4 = Client.Must(Client.CreateChannel(channel4)).Data.(*model.Channel) + + if result, err := Client.AutocompleteChannels("TestAPIName"); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } + + if (*channels)[1].DisplayName != channel2.DisplayName { + t.Fatal("full name didn't match") + } + } + + if result, err := Client.AutocompleteChannels(channel1.Name); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } + } + + if result, err := Client.AutocompleteChannels("BadChannelC"); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if len(*channels) != 0 { + t.Fatal("should have been empty") + } + } + + if result, err := Client.AutocompleteChannels("BadChannelD"); err != nil { + t.Fatal(err) + } else { + channels := result.Data.(*model.ChannelList) + + if len(*channels) != 0 { + t.Fatal("should have been empty") + } + } + + Client.SetTeamId("junk") + + if _, err := Client.AutocompleteChannels("BadChannelD"); err == nil { + t.Fatal("should have failed - bad team id") + } +} diff --git a/api/command_join.go b/api/command_join.go index 2aba1bbd5..0499d503d 100644 --- a/api/command_join.go +++ b/api/command_join.go @@ -33,25 +33,22 @@ func (me *JoinProvider) GetCommand(c *Context) *model.Command { } func (me *JoinProvider) DoCommand(c *Context, channelId string, message string) *model.CommandResponse { - if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId); result.Err != nil { + if result := <-Srv.Store.Channel().GetByName(c.TeamId, message); result.Err != nil { return &model.CommandResponse{Text: c.T("api.command_join.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } else { - channels := result.Data.(*model.ChannelList) + channel := result.Data.(*model.Channel) - for _, v := range *channels { + if channel.Name == message { - if v.Name == message { - - if v.Type != model.CHANNEL_OPEN { - return &model.CommandResponse{Text: c.T("api.command_join.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} - } - - if err, _ := JoinChannelById(c, c.Session.UserId, v.Id); err != nil { - return &model.CommandResponse{Text: c.T("api.command_join.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} - } + if channel.Type != model.CHANNEL_OPEN { + return &model.CommandResponse{Text: c.T("api.command_join.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + } - return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + v.Name, Text: c.T("api.command_join.success"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + if err, _ := JoinChannelById(c, c.Session.UserId, channel.Id); err != nil { + return &model.CommandResponse{Text: c.T("api.command_join.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } + + return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + channel.Name, Text: c.T("api.command_join.success"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } } diff --git a/api/deprecated.go b/api/deprecated.go new file mode 100644 index 000000000..955613fab --- /dev/null +++ b/api/deprecated.go @@ -0,0 +1,39 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api + +import ( + "net/http" + + l4g "github.com/alecthomas/log4go" + "github.com/mattermost/platform/model" + "github.com/mattermost/platform/utils" +) + +// ONLY FOR APIs SCHEDULED TO BE DEPRECATED + +func InitDeprecated() { + l4g.Debug(utils.T("api.channel.init.debug")) + + BaseRoutes.Channels.Handle("/more", ApiUserRequired(getMoreChannels)).Methods("GET") // SCHEDULED FOR DEPRECATION IN 3.7 +} + +func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) { + + // user is already in the team + if !HasPermissionToTeamContext(c, c.TeamId, model.PERMISSION_LIST_TEAM_CHANNELS) { + return + } + + if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId, 0, 100000); result.Err != nil { + c.Err = result.Err + return + } else if HandleEtag(result.Data.(*model.ChannelList).Etag(), w, r) { + return + } else { + data := result.Data.(*model.ChannelList) + w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag()) + w.Write([]byte(data.ToJson())) + } +} diff --git a/api/deprecated_test.go b/api/deprecated_test.go new file mode 100644 index 000000000..000b3950d --- /dev/null +++ b/api/deprecated_test.go @@ -0,0 +1,43 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api + +import ( + "testing" + + "github.com/mattermost/platform/model" +) + +func TestGetMoreChannel(t *testing.T) { + th := Setup().InitBasic() + Client := th.BasicClient + team := th.BasicTeam + + channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) + + channel2 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) + + th.LoginBasic2() + + rget := Client.Must(Client.GetMoreChannels("")) + channels := rget.Data.(*model.ChannelList) + + if (*channels)[0].DisplayName != channel1.DisplayName { + t.Fatal("full name didn't match") + } + + if (*channels)[1].DisplayName != channel2.DisplayName { + t.Fatal("full name didn't match") + } + + // test etag caching + if cache_result, err := Client.GetMoreChannels(rget.Etag); err != nil { + t.Fatal(err) + } else if cache_result.Data.(*model.ChannelList) != nil { + t.Log(cache_result.Data) + t.Fatal("cache should be empty") + } +} diff --git a/api/user.go b/api/user.go index 3a303bee4..26066dabc 100644 --- a/api/user.go +++ b/api/user.go @@ -2712,8 +2712,8 @@ func autocompleteUsersInChannel(c *Context, w http.ResponseWriter, r *http.Reque searchOptions := map[string]bool{} searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true - uchan := Srv.Store.User().SearchInChannel(channelId, term, map[string]bool{}) - nuchan := Srv.Store.User().SearchNotInChannel(teamId, channelId, term, map[string]bool{}) + uchan := Srv.Store.User().SearchInChannel(channelId, term, searchOptions) + nuchan := Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions) autocomplete := &model.UserAutocompleteInChannel{} @@ -2758,7 +2758,10 @@ func autocompleteUsersInTeam(c *Context, w http.ResponseWriter, r *http.Request) } } - uchan := Srv.Store.User().Search(teamId, term, map[string]bool{}) + searchOptions := map[string]bool{} + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + + uchan := Srv.Store.User().Search(teamId, term, searchOptions) autocomplete := &model.UserAutocompleteInTeam{} |