From 609d4f43d9eef504d852fbf02af5473b0d1424c8 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Thu, 2 Feb 2017 09:04:36 -0500 Subject: Implement POST /channels endpoint for APIv4 (#5241) --- api4/api.go | 1 + api4/apitestlib.go | 30 +++++++++ api4/channel.go | 45 ++++++++++++++ api4/channel_test.go | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 api4/channel.go create mode 100644 api4/channel_test.go (limited to 'api4') diff --git a/api4/api.go b/api4/api.go index ace5de30a..2293cdec5 100644 --- a/api4/api.go +++ b/api4/api.go @@ -139,6 +139,7 @@ func InitApi(full bool) { InitUser() InitTeam() + InitChannel() // REMOVE CONDITION WHEN APIv3 REMOVED if full { diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 6b129dd8f..d5706bf2b 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -25,6 +25,7 @@ type TestHelper struct { BasicUser2 *model.User TeamAdminUser *model.User BasicTeam *model.Team + BasicChannel *model.Channel SystemAdminClient *model.Client4 SystemAdminUser *model.User @@ -63,6 +64,7 @@ func (me *TestHelper) InitBasic() *TestHelper { me.TeamAdminUser = me.CreateUser() me.LoginTeamAdmin() me.BasicTeam = me.CreateTeam() + me.BasicChannel = me.CreatePublicChannel() me.BasicUser = me.CreateUser() LinkUserToTeam(me.BasicUser, me.BasicTeam) me.BasicUser2 = me.CreateUser() @@ -128,6 +130,30 @@ func (me *TestHelper) CreateUserWithClient(client *model.Client4) *model.User { return ruser } +func (me *TestHelper) CreatePublicChannel() *model.Channel { + return me.CreateChannelWithClient(me.Client, model.CHANNEL_OPEN) +} + +func (me *TestHelper) CreatePrivateChannel() *model.Channel { + return me.CreateChannelWithClient(me.Client, model.CHANNEL_PRIVATE) +} + +func (me *TestHelper) CreateChannelWithClient(client *model.Client4, channelType string) *model.Channel { + id := model.NewId() + + channel := &model.Channel{ + DisplayName: "dn_" + id, + Name: GenerateTestChannelName(), + Type: channelType, + TeamId: me.BasicTeam.Id, + } + + utils.DisableDebugLogForTest() + rchannel, _ := client.CreateChannel(channel) + utils.EnableDebugLogForTest() + return rchannel +} + func (me *TestHelper) LoginBasic() { me.LoginBasicWithClient(me.Client) } @@ -194,6 +220,10 @@ func GenerateTestTeamName() string { return "faketeam" + model.NewId() } +func GenerateTestChannelName() string { + return "fakechannel" + model.NewId() +} + func VerifyUserEmail(userId string) { store.Must(app.Srv.Store.User().VerifyEmail(userId)) } diff --git a/api4/channel.go b/api4/channel.go new file mode 100644 index 000000000..2ce9e23e5 --- /dev/null +++ b/api4/channel.go @@ -0,0 +1,45 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api4 + +import ( + "net/http" + + l4g "github.com/alecthomas/log4go" + "github.com/mattermost/platform/app" + "github.com/mattermost/platform/model" + "github.com/mattermost/platform/utils" +) + +func InitChannel() { + l4g.Debug(utils.T("api.channel.init.debug")) + + BaseRoutes.Channels.Handle("", ApiSessionRequired(createChannel)).Methods("POST") +} + +func createChannel(c *Context, w http.ResponseWriter, r *http.Request) { + channel := model.ChannelFromJson(r.Body) + if channel == nil { + c.SetInvalidParam("channel") + return + } + + if channel.Type == model.CHANNEL_OPEN && !app.SessionHasPermissionToTeam(c.Session, channel.TeamId, model.PERMISSION_CREATE_PUBLIC_CHANNEL) { + c.SetPermissionError(model.PERMISSION_CREATE_PUBLIC_CHANNEL) + return + } + + if channel.Type == model.CHANNEL_PRIVATE && !app.SessionHasPermissionToTeam(c.Session, channel.TeamId, model.PERMISSION_CREATE_PRIVATE_CHANNEL) { + c.SetPermissionError(model.PERMISSION_CREATE_PRIVATE_CHANNEL) + return + } + + if sc, err := app.CreateChannelWithUser(channel, c.Session.UserId); err != nil { + c.Err = err + return + } else { + c.LogAudit("name=" + channel.Name) + w.Write([]byte(sc.ToJson())) + } +} diff --git a/api4/channel_test.go b/api4/channel_test.go new file mode 100644 index 000000000..e3d0a85bd --- /dev/null +++ b/api4/channel_test.go @@ -0,0 +1,169 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api4 + +import ( + "net/http" + "strconv" + "testing" + + "github.com/mattermost/platform/model" + "github.com/mattermost/platform/utils" +) + +func TestCreateChannel(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + Client := th.Client + team := th.BasicTeam + + channel := &model.Channel{DisplayName: "Test API Name", Name: GenerateTestChannelName(), Type: model.CHANNEL_OPEN, TeamId: team.Id} + private := &model.Channel{DisplayName: "Test API Name", Name: GenerateTestChannelName(), Type: model.CHANNEL_PRIVATE, TeamId: team.Id} + + rchannel, resp := Client.CreateChannel(channel) + CheckNoError(t, resp) + + if rchannel.Name != channel.Name { + t.Fatal("names did not match") + } + + if rchannel.DisplayName != channel.DisplayName { + t.Fatal("display names did not match") + } + + if rchannel.TeamId != channel.TeamId { + t.Fatal("team ids did not match") + } + + rprivate, resp := Client.CreateChannel(private) + CheckNoError(t, resp) + + if rprivate.Name != private.Name { + t.Fatal("names did not match") + } + + if rprivate.Type != model.CHANNEL_PRIVATE { + t.Fatal("wrong channel type") + } + + if rprivate.CreatorId != th.BasicUser.Id { + t.Fatal("wrong creator id") + } + + _, resp = Client.CreateChannel(channel) + CheckErrorMessage(t, resp, "store.sql_channel.save_channel.exists.app_error") + CheckBadRequestStatus(t, resp) + + direct := &model.Channel{DisplayName: "Test API Name", Name: GenerateTestChannelName(), Type: model.CHANNEL_DIRECT, TeamId: team.Id} + _, resp = Client.CreateChannel(direct) + CheckErrorMessage(t, resp, "api.channel.create_channel.direct_channel.app_error") + CheckBadRequestStatus(t, resp) + + Client.Logout() + _, resp = Client.CreateChannel(channel) + CheckUnauthorizedStatus(t, resp) + + userNotOnTeam := th.CreateUser() + Client.Login(userNotOnTeam.Email, userNotOnTeam.Password) + + _, resp = Client.CreateChannel(channel) + CheckForbiddenStatus(t, resp) + + _, resp = Client.CreateChannel(private) + CheckForbiddenStatus(t, resp) + + th.LoginBasic() + + // Check permissions with policy config changes + isLicensed := utils.IsLicensed + license := utils.License + restrictPublicChannel := *utils.Cfg.TeamSettings.RestrictPublicChannelManagement + restrictPrivateChannel := *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement + defer func() { + *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel + *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel + utils.IsLicensed = isLicensed + utils.License = license + utils.SetDefaultRolesBasedOnConfig() + }() + *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL + *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL + utils.SetDefaultRolesBasedOnConfig() + utils.IsLicensed = true + utils.License = &model.License{Features: &model.Features{}} + utils.License.Features.SetDefaults() + + channel.Name = GenerateTestChannelName() + _, resp = Client.CreateChannel(channel) + CheckNoError(t, resp) + + private.Name = GenerateTestChannelName() + _, resp = Client.CreateChannel(private) + CheckNoError(t, resp) + + *utils.Cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_TEAM_ADMIN + *utils.Cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_TEAM_ADMIN + utils.SetDefaultRolesBasedOnConfig() + + _, resp = Client.CreateChannel(channel) + CheckForbiddenStatus(t, resp) + + _, resp = Client.CreateChannel(private) + CheckForbiddenStatus(t, resp) + + th.LoginTeamAdmin() + + channel.Name = GenerateTestChannelName() + _, resp = Client.CreateChannel(channel) + CheckNoError(t, resp) + + private.Name = GenerateTestChannelName() + _, resp = Client.CreateChannel(private) + CheckNoError(t, resp) + + channel.Name = GenerateTestChannelName() + _, resp = th.SystemAdminClient.CreateChannel(channel) + CheckNoError(t, resp) + + private.Name = GenerateTestChannelName() + _, resp = th.SystemAdminClient.CreateChannel(private) + CheckNoError(t, resp) + + *utils.Cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_SYSTEM_ADMIN + *utils.Cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_SYSTEM_ADMIN + utils.SetDefaultRolesBasedOnConfig() + + th.LoginBasic() + + _, resp = Client.CreateChannel(channel) + CheckForbiddenStatus(t, resp) + + _, resp = Client.CreateChannel(private) + CheckForbiddenStatus(t, resp) + + th.LoginTeamAdmin() + + _, resp = Client.CreateChannel(channel) + CheckForbiddenStatus(t, resp) + + _, resp = Client.CreateChannel(private) + CheckForbiddenStatus(t, resp) + + channel.Name = GenerateTestChannelName() + _, resp = th.SystemAdminClient.CreateChannel(channel) + CheckNoError(t, resp) + + private.Name = GenerateTestChannelName() + _, resp = th.SystemAdminClient.CreateChannel(private) + CheckNoError(t, resp) + + if r, err := Client.DoApiPost("/channels", "garbage"); err == nil { + t.Fatal("should have errored") + } else { + if r.StatusCode != http.StatusBadRequest { + t.Log("actual: " + strconv.Itoa(r.StatusCode)) + t.Log("expected: " + strconv.Itoa(http.StatusBadRequest)) + t.Fatal("wrong status code") + } + } +} -- cgit v1.2.3-1-g7c22