diff --git a/api/channel.go b/api/channel.go
index b4a5b78dc3..038a4286af 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -59,6 +59,11 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel.TeamId = c.TeamId
}
+ if err := CanManageChannel(c, channel); err != nil {
+ c.Err = err
+ return
+ }
+
if !c.HasPermissionsToTeam(channel.TeamId, "createChannel") {
return
}
@@ -178,6 +183,32 @@ func CreateDefaultChannels(c *Context, teamId string) ([]*model.Channel, *model.
return channels, nil
}
+func CanManageChannel(c *Context, channel *model.Channel) *model.AppError {
+ if utils.IsLicensed {
+ if channel.Type == model.CHANNEL_OPEN {
+ if *utils.Cfg.TeamSettings.RestrictPublicChannelManagement == model.PERMISSIONS_SYSTEM_ADMIN && !c.IsSystemAdmin() {
+ return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.public_restricted_system_admin.app_error", nil, "")
+ }
+
+ if *utils.Cfg.TeamSettings.RestrictPublicChannelManagement == model.PERMISSIONS_TEAM_ADMIN && !c.IsTeamAdmin() {
+ return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.public_restricted_team_admin.app_error", nil, "")
+ }
+ }
+
+ if channel.Type == model.CHANNEL_PRIVATE {
+ if *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement == model.PERMISSIONS_SYSTEM_ADMIN && !c.IsSystemAdmin() {
+ return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.private_restricted_system_admin.app_error", nil, "")
+ }
+
+ if *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement == model.PERMISSIONS_TEAM_ADMIN && !c.IsTeamAdmin() {
+ return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.private_restricted_team_admin.app_error", nil, "")
+ }
+ }
+ }
+
+ return nil
+}
+
func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel := model.ChannelFromJson(r.Body)
@@ -198,15 +229,14 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
oldChannel := cresult.Data.(*model.Channel)
- channelMember := cmcresult.Data.(model.ChannelMember)
+ // Don't need to do anything with channel member, just wanted to confirm it exists
- if !c.HasPermissionsToTeam(oldChannel.TeamId, "updateChannel") {
+ if err := CanManageChannel(c, oldChannel); err != nil {
+ c.Err = err
return
}
- if !strings.Contains(channelMember.Roles, model.CHANNEL_ROLE_ADMIN) && !c.IsTeamAdmin() {
- c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.permission.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
+ if !c.HasPermissionsToTeam(oldChannel.TeamId, "updateChannel") {
return
}
@@ -275,7 +305,12 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
channel := cresult.Data.(*model.Channel)
- // Don't need to do anything channel member, just wanted to confirm it exists
+ // Don't need to do anything with channel member, just wanted to confirm it exists
+
+ if err := CanManageChannel(c, channel); err != nil {
+ c.Err = err
+ return
+ }
if channel.TeamId != "" && !c.HasPermissionsToTeam(channel.TeamId, "updateChannelHeader") {
return
@@ -348,7 +383,12 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
channel := cresult.Data.(*model.Channel)
- // Don't need to do anything channel member, just wanted to confirm it exists
+ // Don't need to do anything with channel member, just wanted to confirm it exists
+
+ if err := CanManageChannel(c, channel); err != nil {
+ c.Err = err
+ return
+ }
if !c.HasPermissionsToTeam(channel.TeamId, "updateChannelPurpose") {
return
@@ -646,6 +686,7 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
sc := Srv.Store.Channel().Get(id)
scm := Srv.Store.Channel().GetMember(id, c.Session.UserId)
+ cmc := Srv.Store.Channel().GetMemberCount(id)
uc := Srv.Store.User().Get(c.Session.UserId)
ihc := Srv.Store.Webhook().GetIncomingByChannel(id)
ohc := Srv.Store.Webhook().GetOutgoingByChannel(id)
@@ -659,6 +700,9 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
} else if scmresult := <-scm; scmresult.Err != nil {
c.Err = scmresult.Err
return
+ } else if cmcresult := <-cmc; cmcresult.Err != nil {
+ c.Err = cmcresult.Err
+ return
} else if ihcresult := <-ihc; ihcresult.Err != nil {
c.Err = ihcresult.Err
return
@@ -667,18 +711,21 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
channel := cresult.Data.(*model.Channel)
+ memberCount := cmcresult.Data.(int64)
user := uresult.Data.(*model.User)
- channelMember := scmresult.Data.(model.ChannelMember)
incomingHooks := ihcresult.Data.([]*model.IncomingWebhook)
outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook)
+ // Don't need to do anything with channel member, just wanted to confirm it exists
- if !c.HasPermissionsToTeam(channel.TeamId, "deleteChannel") {
- return
+ // Allow delete if user is the only member left in channel
+ if memberCount > 1 {
+ if err := CanManageChannel(c, channel); err != nil {
+ c.Err = err
+ return
+ }
}
- if !strings.Contains(channelMember.Roles, model.CHANNEL_ROLE_ADMIN) && !c.IsTeamAdmin() {
- c.Err = model.NewLocAppError("deleteChannel", "api.channel.delete_channel.permissions.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
+ if !c.HasPermissionsToTeam(channel.TeamId, "deleteChannel") {
return
}
diff --git a/api/channel_test.go b/api/channel_test.go
index 7480dea233..ac47d4eeda 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -14,8 +14,9 @@ import (
)
func TestCreateChannel(t *testing.T) {
- th := Setup().InitBasic()
+ th := Setup().InitBasic().InitSystemAdmin()
Client := th.BasicClient
+ SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam
Client.Must(Client.Logout())
team2 := th.CreateTeam(th.BasicClient)
@@ -74,6 +75,12 @@ func TestCreateChannel(t *testing.T) {
t.Fatal(err)
}
+ channel = model.Channel{DisplayName: "Channel With No TeamId", Name: "aaaa" + model.NewId() + "abbb", Type: model.CHANNEL_OPEN, TeamId: ""}
+
+ if _, err := Client.CreateChannel(&channel); err != nil {
+ t.Fatal(err)
+ }
+
channel = model.Channel{DisplayName: "Test API Name", Name: model.NewId() + "__" + model.NewId(), Type: model.CHANNEL_OPEN, TeamId: team.Id}
if _, err := Client.CreateChannel(&channel); err == nil {
@@ -85,6 +92,72 @@ func TestCreateChannel(t *testing.T) {
if _, err := Client.CreateChannel(&channel); err == nil {
t.Fatal("Should have errored out on direct channel type")
}
+
+ isLicensed := utils.IsLicensed
+ 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.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
+ utils.IsLicensed = true
+
+ channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
+ channel3 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
+ if _, err := Client.CreateChannel(channel2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.CreateChannel(channel3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+
+ channel2.Name = "a" + model.NewId() + "a"
+ channel3.Name = "a" + model.NewId() + "a"
+ if _, err := Client.CreateChannel(channel2); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+ if _, err := Client.CreateChannel(channel3); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+
+ UpdateUserToTeamAdmin(th.BasicUser, team)
+ Client.Logout()
+ th.LoginBasic()
+ Client.SetTeamId(team.Id)
+
+ if _, err := Client.CreateChannel(channel2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.CreateChannel(channel3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+
+ channel2.Name = "a" + model.NewId() + "a"
+ channel3.Name = "a" + model.NewId() + "a"
+ if _, err := Client.CreateChannel(channel2); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+ if _, err := Client.CreateChannel(channel3); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+
+ LinkUserToTeam(th.SystemAdminUser, team)
+
+ if _, err := SystemAdminClient.CreateChannel(channel2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := SystemAdminClient.CreateChannel(channel3); err != nil {
+ t.Fatal(err)
+ }
}
func TestCreateDirectChannel(t *testing.T) {
@@ -129,7 +202,7 @@ func TestCreateDirectChannel(t *testing.T) {
}
func TestUpdateChannel(t *testing.T) {
- th := Setup().InitSystemAdmin()
+ th := Setup().InitBasic().InitSystemAdmin()
Client := th.SystemAdminClient
team := th.SystemAdminTeam
sysAdminUser := th.SystemAdminUser
@@ -193,6 +266,7 @@ func TestUpdateChannel(t *testing.T) {
}
Client.Login(sysAdminUser.Email, sysAdminUser.Password)
+ LinkUserToTeam(sysAdminUser, team)
Client.Must(Client.JoinChannel(channel1.Id))
if _, err := Client.UpdateChannel(upChannel1); err != nil {
@@ -204,11 +278,82 @@ func TestUpdateChannel(t *testing.T) {
if _, err := Client.UpdateChannel(upChannel1); err == nil {
t.Fatal("should have failed - channel deleted")
}
+
+ isLicensed := utils.IsLicensed
+ 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.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
+ utils.IsLicensed = true
+
+ channel2 := th.CreateChannel(Client, team)
+ channel3 := th.CreatePrivateChannel(Client, team)
+
+ LinkUserToTeam(th.BasicUser, team)
+
+ Client.Must(Client.AddChannelMember(channel2.Id, th.BasicUser.Id))
+ Client.Must(Client.AddChannelMember(channel3.Id, th.BasicUser.Id))
+
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+
+ if _, err := Client.UpdateChannel(channel2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.UpdateChannel(channel3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+
+ if _, err := Client.UpdateChannel(channel2); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+ if _, err := Client.UpdateChannel(channel3); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+
+ UpdateUserToTeamAdmin(th.BasicUser, team)
+ Client.Logout()
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+ Client.SetTeamId(team.Id)
+
+ if _, err := Client.UpdateChannel(channel2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.UpdateChannel(channel3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+
+ if _, err := Client.UpdateChannel(channel2); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+ if _, err := Client.UpdateChannel(channel3); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+
+ th.LoginSystemAdmin()
+
+ if _, err := Client.UpdateChannel(channel2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.UpdateChannel(channel3); err != nil {
+ t.Fatal(err)
+ }
}
func TestUpdateChannelHeader(t *testing.T) {
- th := Setup().InitBasic()
+ th := Setup().InitBasic().InitSystemAdmin()
Client := th.BasicClient
+ SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
@@ -266,11 +411,89 @@ func TestUpdateChannelHeader(t *testing.T) {
if _, err := Client.UpdateChannelHeader(data); err == nil {
t.Fatal("should have errored non-channel member trying to update header")
}
+
+ isLicensed := utils.IsLicensed
+ 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.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
+ utils.IsLicensed = true
+
+ th.LoginBasic()
+ channel2 := th.CreateChannel(Client, team)
+ channel3 := th.CreatePrivateChannel(Client, team)
+
+ data2 := make(map[string]string)
+ data2["channel_id"] = channel2.Id
+ data2["channel_header"] = "new header"
+
+ data3 := make(map[string]string)
+ data3["channel_id"] = channel3.Id
+ data3["channel_header"] = "new header"
+
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+
+ if _, err := Client.UpdateChannelHeader(data2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.UpdateChannelHeader(data3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+
+ if _, err := Client.UpdateChannelHeader(data2); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+ if _, err := Client.UpdateChannelHeader(data3); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+
+ UpdateUserToTeamAdmin(th.BasicUser, team)
+ Client.Logout()
+ th.LoginBasic()
+ Client.SetTeamId(team.Id)
+
+ if _, err := Client.UpdateChannelHeader(data2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.UpdateChannelHeader(data3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+
+ if _, err := Client.UpdateChannelHeader(data2); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+ if _, err := Client.UpdateChannelHeader(data3); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+
+ LinkUserToTeam(th.SystemAdminUser, team)
+ Client.Must(Client.AddChannelMember(channel2.Id, th.SystemAdminUser.Id))
+ Client.Must(Client.AddChannelMember(channel3.Id, th.SystemAdminUser.Id))
+ th.LoginSystemAdmin()
+
+ if _, err := SystemAdminClient.UpdateChannelHeader(data2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := SystemAdminClient.UpdateChannelHeader(data3); err != nil {
+ t.Fatal(err)
+ }
}
func TestUpdateChannelPurpose(t *testing.T) {
- th := Setup().InitBasic()
+ th := Setup().InitBasic().InitSystemAdmin()
Client := th.BasicClient
+ SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
@@ -314,6 +537,83 @@ func TestUpdateChannelPurpose(t *testing.T) {
if _, err := Client.UpdateChannelPurpose(data); err == nil {
t.Fatal("should have errored non-channel member trying to update purpose")
}
+
+ isLicensed := utils.IsLicensed
+ 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.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
+ utils.IsLicensed = true
+
+ th.LoginBasic()
+ channel2 := th.CreateChannel(Client, team)
+ channel3 := th.CreatePrivateChannel(Client, team)
+
+ data2 := make(map[string]string)
+ data2["channel_id"] = channel2.Id
+ data2["channel_purpose"] = "new purpose"
+
+ data3 := make(map[string]string)
+ data3["channel_id"] = channel3.Id
+ data3["channel_purpose"] = "new purpose"
+
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+
+ if _, err := Client.UpdateChannelPurpose(data2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.UpdateChannelPurpose(data3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+
+ if _, err := Client.UpdateChannelPurpose(data2); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+ if _, err := Client.UpdateChannelPurpose(data3); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+
+ UpdateUserToTeamAdmin(th.BasicUser, team)
+ Client.Logout()
+ th.LoginBasic()
+ Client.SetTeamId(team.Id)
+
+ if _, err := Client.UpdateChannelPurpose(data2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.UpdateChannelPurpose(data3); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+
+ if _, err := Client.UpdateChannelPurpose(data2); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+ if _, err := Client.UpdateChannelPurpose(data3); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+
+ LinkUserToTeam(th.SystemAdminUser, team)
+ Client.Must(Client.AddChannelMember(channel2.Id, th.SystemAdminUser.Id))
+ Client.Must(Client.AddChannelMember(channel3.Id, th.SystemAdminUser.Id))
+ th.LoginSystemAdmin()
+
+ if _, err := SystemAdminClient.UpdateChannelPurpose(data2); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := SystemAdminClient.UpdateChannelPurpose(data3); err != nil {
+ t.Fatal(err)
+ }
}
func TestGetChannel(t *testing.T) {
@@ -572,7 +872,7 @@ func TestLeaveChannel(t *testing.T) {
}
func TestDeleteChannel(t *testing.T) {
- th := Setup().InitSystemAdmin()
+ th := Setup().InitBasic().InitSystemAdmin()
Client := th.SystemAdminClient
team := th.SystemAdminTeam
userSystemAdmin := th.SystemAdminUser
@@ -619,8 +919,8 @@ func TestDeleteChannel(t *testing.T) {
Client.Must(Client.JoinChannel(channel2.Id))
- if _, err := Client.DeleteChannel(channel2.Id); err == nil {
- t.Fatal("should have failed to delete channel you're not an admin of")
+ if _, err := Client.DeleteChannel(channel2.Id); err != nil {
+ t.Fatal(err)
}
rget := Client.Must(Client.GetChannels(""))
@@ -640,6 +940,8 @@ func TestDeleteChannel(t *testing.T) {
Client.Login(userStd.Email, userStd.Password)
Client.SetTeamId(team.Id)
+ channel2 = th.CreateChannel(Client, team)
+
if _, err := Client.DeleteChannel(channel2.Id); err != nil {
t.Fatal(err)
}
@@ -657,6 +959,102 @@ func TestDeleteChannel(t *testing.T) {
if _, err := Client.DeleteChannel(channel3.Id); err == nil {
t.Fatal("should have failed - channel already deleted")
}
+
+ isLicensed := utils.IsLicensed
+ 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.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
+ utils.IsLicensed = true
+
+ th.LoginSystemAdmin()
+ LinkUserToTeam(th.BasicUser, team)
+
+ channel2 = th.CreateChannel(Client, team)
+ channel3 = th.CreatePrivateChannel(Client, team)
+ channel4 := th.CreateChannel(Client, team)
+ Client.Must(Client.AddChannelMember(channel2.Id, th.BasicUser.Id))
+ Client.Must(Client.AddChannelMember(channel3.Id, th.BasicUser.Id))
+ Client.Must(Client.AddChannelMember(channel4.Id, th.BasicUser.Id))
+ Client.Must(Client.LeaveChannel(channel4.Id))
+
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+
+ if _, err := Client.DeleteChannel(channel2.Id); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.DeleteChannel(channel3.Id); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+
+ th.LoginSystemAdmin()
+
+ channel2 = th.CreateChannel(Client, team)
+ channel3 = th.CreatePrivateChannel(Client, team)
+ Client.Must(Client.AddChannelMember(channel2.Id, th.BasicUser.Id))
+ Client.Must(Client.AddChannelMember(channel3.Id, th.BasicUser.Id))
+
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+
+ if _, err := Client.DeleteChannel(channel2.Id); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+ if _, err := Client.DeleteChannel(channel3.Id); err == nil {
+ t.Fatal("should have errored not team admin")
+ }
+
+ UpdateUserToTeamAdmin(th.BasicUser, team)
+ Client.Logout()
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+ Client.SetTeamId(team.Id)
+
+ if _, err := Client.DeleteChannel(channel2.Id); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.DeleteChannel(channel3.Id); err != nil {
+ t.Fatal(err)
+ }
+
+ *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+
+ th.LoginSystemAdmin()
+
+ channel2 = th.CreateChannel(Client, team)
+ channel3 = th.CreatePrivateChannel(Client, team)
+ Client.Must(Client.AddChannelMember(channel2.Id, th.BasicUser.Id))
+ Client.Must(Client.AddChannelMember(channel3.Id, th.BasicUser.Id))
+
+ Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+
+ if _, err := Client.DeleteChannel(channel2.Id); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+ if _, err := Client.DeleteChannel(channel3.Id); err == nil {
+ t.Fatal("should have errored not system admin")
+ }
+
+ // Only one left in channel, should be able to delete
+ if _, err := Client.DeleteChannel(channel4.Id); err != nil {
+ t.Fatal(err)
+ }
+
+ th.LoginSystemAdmin()
+
+ if _, err := Client.DeleteChannel(channel2.Id); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := Client.DeleteChannel(channel3.Id); err != nil {
+ t.Fatal(err)
+ }
}
func TestGetChannelExtraInfo(t *testing.T) {
diff --git a/api/team.go b/api/team.go
index 9b23a63afc..50e32e6259 100644
--- a/api/team.go
+++ b/api/team.go
@@ -400,12 +400,12 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
}
if utils.IsLicensed {
- if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.TEAM_INVITE_SYSTEM_ADMIN && !c.IsSystemAdmin() {
+ if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_SYSTEM_ADMIN && !c.IsSystemAdmin() {
c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_system_admin.app_error", nil, "")
return
}
- if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.TEAM_INVITE_TEAM_ADMIN && !c.IsTeamAdmin() {
+ if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_TEAM_ADMIN && !c.IsTeamAdmin() {
c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_team_admin.app_error", nil, "")
return
}
diff --git a/api/team_test.go b/api/team_test.go
index 91c73bed54..a62ffcdb58 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -399,7 +399,7 @@ func TestInviteMembers(t *testing.T) {
defer func() {
*utils.Cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite
}()
- *utils.Cfg.TeamSettings.RestrictTeamInvite = model.TEAM_INVITE_TEAM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN
th.LoginBasic2()
LinkUserToTeam(th.BasicUser2, team)
@@ -427,7 +427,7 @@ func TestInviteMembers(t *testing.T) {
t.Fatal(err)
}
- *utils.Cfg.TeamSettings.RestrictTeamInvite = model.TEAM_INVITE_SYSTEM_ADMIN
+ *utils.Cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_SYSTEM_ADMIN
if _, err := Client.InviteMembers(invites); err == nil {
t.Fatal("should have errored not system admin and licensed")
diff --git a/config/config.json b/config/config.json
index ec021045f7..c70ace9ff0 100644
--- a/config/config.json
+++ b/config/config.json
@@ -38,7 +38,9 @@
"EnableCustomBrand": false,
"CustomBrandText": "",
"RestrictDirectMessage": "any",
- "RestrictTeamInvite": "system_admin"
+ "RestrictTeamInvite": "all",
+ "RestrictPublicChannelManagement": "all",
+ "RestrictPrivateChannelManagement": "all"
},
"SqlSettings": {
"DriverName": "mysql",
diff --git a/i18n/en.json b/i18n/en.json
index 69b18adf37..8436d48d9e 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -311,6 +311,22 @@
"id": "api.channel.update_channel.deleted.app_error",
"translation": "The channel has been archived or deleted"
},
+ {
+ "id": "api.channel.can_manage_channel.public_restricted_system_admin.app_error",
+ "translation": "Public Channel management and creation is restricted to System Administrators."
+ },
+ {
+ "id": "api.channel.can_manage_channel.public_restricted_team_admin.app_error",
+ "translation": "Public Channel management and creation is restricted to Team and System Administrators."
+ },
+ {
+ "id": "api.channel.can_manage_channel.private_restricted_system_admin.app_error",
+ "translation": "Private Group management and creation is restricted to System Administrators."
+ },
+ {
+ "id": "api.channel.can_manage_channel.private_restricted_team_admin.app_error",
+ "translation": "Private Group management and creation is restricted to Team and System Administrators."
+ },
{
"id": "api.channel.update_channel.permission.app_error",
"translation": "You do not have the appropriate permissions"
diff --git a/model/config.go b/model/config.go
index 32994a279e..61c39bc5bd 100644
--- a/model/config.go
+++ b/model/config.go
@@ -32,9 +32,9 @@ const (
DIRECT_MESSAGE_ANY = "any"
DIRECT_MESSAGE_TEAM = "team"
- TEAM_INVITE_ALL = "all"
- TEAM_INVITE_TEAM_ADMIN = "team_admin"
- TEAM_INVITE_SYSTEM_ADMIN = "system_admin"
+ PERMISSIONS_ALL = "all"
+ PERMISSIONS_TEAM_ADMIN = "team_admin"
+ PERMISSIONS_SYSTEM_ADMIN = "system_admin"
FAKE_SETTING = "********************************"
@@ -169,17 +169,19 @@ type SupportSettings struct {
}
type TeamSettings struct {
- SiteName string
- MaxUsersPerTeam int
- EnableTeamCreation bool
- EnableUserCreation bool
- EnableOpenServer *bool
- RestrictCreationToDomains string
- RestrictTeamNames *bool
- EnableCustomBrand *bool
- CustomBrandText *string
- RestrictDirectMessage *string
- RestrictTeamInvite *string
+ SiteName string
+ MaxUsersPerTeam int
+ EnableTeamCreation bool
+ EnableUserCreation bool
+ EnableOpenServer *bool
+ RestrictCreationToDomains string
+ RestrictTeamNames *bool
+ EnableCustomBrand *bool
+ CustomBrandText *string
+ RestrictDirectMessage *string
+ RestrictTeamInvite *string
+ RestrictPublicChannelManagement *string
+ RestrictPrivateChannelManagement *string
}
type LdapSettings struct {
@@ -381,7 +383,17 @@ func (o *Config) SetDefaults() {
if o.TeamSettings.RestrictTeamInvite == nil {
o.TeamSettings.RestrictTeamInvite = new(string)
- *o.TeamSettings.RestrictTeamInvite = TEAM_INVITE_ALL
+ *o.TeamSettings.RestrictTeamInvite = PERMISSIONS_ALL
+ }
+
+ if o.TeamSettings.RestrictPublicChannelManagement == nil {
+ o.TeamSettings.RestrictPublicChannelManagement = new(string)
+ *o.TeamSettings.RestrictPublicChannelManagement = PERMISSIONS_ALL
+ }
+
+ if o.TeamSettings.RestrictPrivateChannelManagement == nil {
+ o.TeamSettings.RestrictPrivateChannelManagement = new(string)
+ *o.TeamSettings.RestrictPrivateChannelManagement = PERMISSIONS_ALL
}
if o.EmailSettings.EnableSignInWithEmail == nil {
diff --git a/utils/config.go b/utils/config.go
index abb24c0850..1fbed5d7bc 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -215,6 +215,8 @@ func getClientConfig(c *model.Config) map[string]string {
props["RestrictTeamNames"] = strconv.FormatBool(*c.TeamSettings.RestrictTeamNames)
props["RestrictDirectMessage"] = *c.TeamSettings.RestrictDirectMessage
props["RestrictTeamInvite"] = *c.TeamSettings.RestrictTeamInvite
+ props["RestrictPublicChannelManagement"] = *c.TeamSettings.RestrictPublicChannelManagement
+ props["RestrictPrivateChannelManagement"] = *c.TeamSettings.RestrictPrivateChannelManagement
props["EnableOAuthServiceProvider"] = strconv.FormatBool(c.ServiceSettings.EnableOAuthServiceProvider)
props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey
diff --git a/webapp/components/admin_console/policy_settings.jsx b/webapp/components/admin_console/policy_settings.jsx
index 7fe8e94605..c7031af7bb 100644
--- a/webapp/components/admin_console/policy_settings.jsx
+++ b/webapp/components/admin_console/policy_settings.jsx
@@ -21,12 +21,16 @@ export default class PolicySettings extends AdminSettings {
this.renderSettings = this.renderSettings.bind(this);
this.state = Object.assign(this.state, {
- restrictTeamInvite: props.config.TeamSettings.RestrictTeamInvite
+ restrictTeamInvite: props.config.TeamSettings.RestrictTeamInvite,
+ restrictPublicChannelManagement: props.config.TeamSettings.RestrictPublicChannelManagement,
+ restrictPrivateChannelManagement: props.config.TeamSettings.RestrictPrivateChannelManagement
});
}
getConfigFromState(config) {
config.TeamSettings.RestrictTeamInvite = this.state.restrictTeamInvite;
+ config.TeamSettings.RestrictPublicChannelManagement = this.state.restrictPublicChannelManagement;
+ config.TeamSettings.RestrictPrivateChannelManagement = this.state.restrictPrivateChannelManagement;
return config;
}
@@ -48,9 +52,9 @@ export default class PolicySettings extends AdminSettings {
+
-
{this.props.serverError}
; } + let createPublicChannelLink = ( + +