PLT-3346/PLT-3342/PLT-3360 EE: Add the ability to restrict channel management permissions (#3453)

* EE: Add the ability to restrict channel management permissions

* Always allow last user in a channel to delete that channel
Этот коммит содержится в:
Joram Wilander
2016-07-06 08:23:24 -04:00
коммит произвёл GitHub
родитель 19d452c74e
Коммит 5f7cb8cfbf
20 изменённых файлов: 871 добавлений и 180 удалений

Просмотреть файл

@@ -59,6 +59,11 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel.TeamId = c.TeamId channel.TeamId = c.TeamId
} }
if err := CanManageChannel(c, channel); err != nil {
c.Err = err
return
}
if !c.HasPermissionsToTeam(channel.TeamId, "createChannel") { if !c.HasPermissionsToTeam(channel.TeamId, "createChannel") {
return return
} }
@@ -178,6 +183,32 @@ func CreateDefaultChannels(c *Context, teamId string) ([]*model.Channel, *model.
return channels, nil 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) { func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel := model.ChannelFromJson(r.Body) channel := model.ChannelFromJson(r.Body)
@@ -198,15 +229,14 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} else { } else {
oldChannel := cresult.Data.(*model.Channel) 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 return
} }
if !strings.Contains(channelMember.Roles, model.CHANNEL_ROLE_ADMIN) && !c.IsTeamAdmin() { if !c.HasPermissionsToTeam(oldChannel.TeamId, "updateChannel") {
c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.permission.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return return
} }
@@ -275,7 +305,12 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} else { } else {
channel := cresult.Data.(*model.Channel) 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") { if channel.TeamId != "" && !c.HasPermissionsToTeam(channel.TeamId, "updateChannelHeader") {
return return
@@ -348,7 +383,12 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} else { } else {
channel := cresult.Data.(*model.Channel) 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") { if !c.HasPermissionsToTeam(channel.TeamId, "updateChannelPurpose") {
return return
@@ -646,6 +686,7 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
sc := Srv.Store.Channel().Get(id) sc := Srv.Store.Channel().Get(id)
scm := Srv.Store.Channel().GetMember(id, c.Session.UserId) scm := Srv.Store.Channel().GetMember(id, c.Session.UserId)
cmc := Srv.Store.Channel().GetMemberCount(id)
uc := Srv.Store.User().Get(c.Session.UserId) uc := Srv.Store.User().Get(c.Session.UserId)
ihc := Srv.Store.Webhook().GetIncomingByChannel(id) ihc := Srv.Store.Webhook().GetIncomingByChannel(id)
ohc := Srv.Store.Webhook().GetOutgoingByChannel(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 { } else if scmresult := <-scm; scmresult.Err != nil {
c.Err = scmresult.Err c.Err = scmresult.Err
return return
} else if cmcresult := <-cmc; cmcresult.Err != nil {
c.Err = cmcresult.Err
return
} else if ihcresult := <-ihc; ihcresult.Err != nil { } else if ihcresult := <-ihc; ihcresult.Err != nil {
c.Err = ihcresult.Err c.Err = ihcresult.Err
return return
@@ -667,18 +711,21 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} else { } else {
channel := cresult.Data.(*model.Channel) channel := cresult.Data.(*model.Channel)
memberCount := cmcresult.Data.(int64)
user := uresult.Data.(*model.User) user := uresult.Data.(*model.User)
channelMember := scmresult.Data.(model.ChannelMember)
incomingHooks := ihcresult.Data.([]*model.IncomingWebhook) incomingHooks := ihcresult.Data.([]*model.IncomingWebhook)
outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook) 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") { // Allow delete if user is the only member left in channel
return 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() { if !c.HasPermissionsToTeam(channel.TeamId, "deleteChannel") {
c.Err = model.NewLocAppError("deleteChannel", "api.channel.delete_channel.permissions.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return return
} }

Просмотреть файл

@@ -14,8 +14,9 @@ import (
) )
func TestCreateChannel(t *testing.T) { func TestCreateChannel(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic().InitSystemAdmin()
Client := th.BasicClient Client := th.BasicClient
SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam team := th.BasicTeam
Client.Must(Client.Logout()) Client.Must(Client.Logout())
team2 := th.CreateTeam(th.BasicClient) team2 := th.CreateTeam(th.BasicClient)
@@ -74,6 +75,12 @@ func TestCreateChannel(t *testing.T) {
t.Fatal(err) 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} 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 { if _, err := Client.CreateChannel(&channel); err == nil {
@@ -85,6 +92,72 @@ func TestCreateChannel(t *testing.T) {
if _, err := Client.CreateChannel(&channel); err == nil { if _, err := Client.CreateChannel(&channel); err == nil {
t.Fatal("Should have errored out on direct channel type") 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) { func TestCreateDirectChannel(t *testing.T) {
@@ -129,7 +202,7 @@ func TestCreateDirectChannel(t *testing.T) {
} }
func TestUpdateChannel(t *testing.T) { func TestUpdateChannel(t *testing.T) {
th := Setup().InitSystemAdmin() th := Setup().InitBasic().InitSystemAdmin()
Client := th.SystemAdminClient Client := th.SystemAdminClient
team := th.SystemAdminTeam team := th.SystemAdminTeam
sysAdminUser := th.SystemAdminUser sysAdminUser := th.SystemAdminUser
@@ -193,6 +266,7 @@ func TestUpdateChannel(t *testing.T) {
} }
Client.Login(sysAdminUser.Email, sysAdminUser.Password) Client.Login(sysAdminUser.Email, sysAdminUser.Password)
LinkUserToTeam(sysAdminUser, team)
Client.Must(Client.JoinChannel(channel1.Id)) Client.Must(Client.JoinChannel(channel1.Id))
if _, err := Client.UpdateChannel(upChannel1); err != nil { if _, err := Client.UpdateChannel(upChannel1); err != nil {
@@ -204,11 +278,82 @@ func TestUpdateChannel(t *testing.T) {
if _, err := Client.UpdateChannel(upChannel1); err == nil { if _, err := Client.UpdateChannel(upChannel1); err == nil {
t.Fatal("should have failed - channel deleted") 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) { func TestUpdateChannelHeader(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic().InitSystemAdmin()
Client := th.BasicClient Client := th.BasicClient
SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam team := th.BasicTeam
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} 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 { if _, err := Client.UpdateChannelHeader(data); err == nil {
t.Fatal("should have errored non-channel member trying to update header") 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) { func TestUpdateChannelPurpose(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic().InitSystemAdmin()
Client := th.BasicClient Client := th.BasicClient
SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam team := th.BasicTeam
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} 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 { if _, err := Client.UpdateChannelPurpose(data); err == nil {
t.Fatal("should have errored non-channel member trying to update purpose") 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) { func TestGetChannel(t *testing.T) {
@@ -572,7 +872,7 @@ func TestLeaveChannel(t *testing.T) {
} }
func TestDeleteChannel(t *testing.T) { func TestDeleteChannel(t *testing.T) {
th := Setup().InitSystemAdmin() th := Setup().InitBasic().InitSystemAdmin()
Client := th.SystemAdminClient Client := th.SystemAdminClient
team := th.SystemAdminTeam team := th.SystemAdminTeam
userSystemAdmin := th.SystemAdminUser userSystemAdmin := th.SystemAdminUser
@@ -619,8 +919,8 @@ func TestDeleteChannel(t *testing.T) {
Client.Must(Client.JoinChannel(channel2.Id)) Client.Must(Client.JoinChannel(channel2.Id))
if _, err := Client.DeleteChannel(channel2.Id); err == nil { if _, err := Client.DeleteChannel(channel2.Id); err != nil {
t.Fatal("should have failed to delete channel you're not an admin of") t.Fatal(err)
} }
rget := Client.Must(Client.GetChannels("")) rget := Client.Must(Client.GetChannels(""))
@@ -640,6 +940,8 @@ func TestDeleteChannel(t *testing.T) {
Client.Login(userStd.Email, userStd.Password) Client.Login(userStd.Email, userStd.Password)
Client.SetTeamId(team.Id) Client.SetTeamId(team.Id)
channel2 = th.CreateChannel(Client, team)
if _, err := Client.DeleteChannel(channel2.Id); err != nil { if _, err := Client.DeleteChannel(channel2.Id); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -657,6 +959,102 @@ func TestDeleteChannel(t *testing.T) {
if _, err := Client.DeleteChannel(channel3.Id); err == nil { if _, err := Client.DeleteChannel(channel3.Id); err == nil {
t.Fatal("should have failed - channel already deleted") 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) { func TestGetChannelExtraInfo(t *testing.T) {

Просмотреть файл

@@ -400,12 +400,12 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
} }
if utils.IsLicensed { 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, "") c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_system_admin.app_error", nil, "")
return 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, "") c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_team_admin.app_error", nil, "")
return return
} }

Просмотреть файл

@@ -399,7 +399,7 @@ func TestInviteMembers(t *testing.T) {
defer func() { defer func() {
*utils.Cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite *utils.Cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite
}() }()
*utils.Cfg.TeamSettings.RestrictTeamInvite = model.TEAM_INVITE_TEAM_ADMIN *utils.Cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN
th.LoginBasic2() th.LoginBasic2()
LinkUserToTeam(th.BasicUser2, team) LinkUserToTeam(th.BasicUser2, team)
@@ -427,7 +427,7 @@ func TestInviteMembers(t *testing.T) {
t.Fatal(err) 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 { if _, err := Client.InviteMembers(invites); err == nil {
t.Fatal("should have errored not system admin and licensed") t.Fatal("should have errored not system admin and licensed")

Просмотреть файл

@@ -38,7 +38,9 @@
"EnableCustomBrand": false, "EnableCustomBrand": false,
"CustomBrandText": "", "CustomBrandText": "",
"RestrictDirectMessage": "any", "RestrictDirectMessage": "any",
"RestrictTeamInvite": "system_admin" "RestrictTeamInvite": "all",
"RestrictPublicChannelManagement": "all",
"RestrictPrivateChannelManagement": "all"
}, },
"SqlSettings": { "SqlSettings": {
"DriverName": "mysql", "DriverName": "mysql",

Просмотреть файл

@@ -311,6 +311,22 @@
"id": "api.channel.update_channel.deleted.app_error", "id": "api.channel.update_channel.deleted.app_error",
"translation": "The channel has been archived or deleted" "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", "id": "api.channel.update_channel.permission.app_error",
"translation": "You do not have the appropriate permissions" "translation": "You do not have the appropriate permissions"

Просмотреть файл

@@ -32,9 +32,9 @@ const (
DIRECT_MESSAGE_ANY = "any" DIRECT_MESSAGE_ANY = "any"
DIRECT_MESSAGE_TEAM = "team" DIRECT_MESSAGE_TEAM = "team"
TEAM_INVITE_ALL = "all" PERMISSIONS_ALL = "all"
TEAM_INVITE_TEAM_ADMIN = "team_admin" PERMISSIONS_TEAM_ADMIN = "team_admin"
TEAM_INVITE_SYSTEM_ADMIN = "system_admin" PERMISSIONS_SYSTEM_ADMIN = "system_admin"
FAKE_SETTING = "********************************" FAKE_SETTING = "********************************"
@@ -169,17 +169,19 @@ type SupportSettings struct {
} }
type TeamSettings struct { type TeamSettings struct {
SiteName string SiteName string
MaxUsersPerTeam int MaxUsersPerTeam int
EnableTeamCreation bool EnableTeamCreation bool
EnableUserCreation bool EnableUserCreation bool
EnableOpenServer *bool EnableOpenServer *bool
RestrictCreationToDomains string RestrictCreationToDomains string
RestrictTeamNames *bool RestrictTeamNames *bool
EnableCustomBrand *bool EnableCustomBrand *bool
CustomBrandText *string CustomBrandText *string
RestrictDirectMessage *string RestrictDirectMessage *string
RestrictTeamInvite *string RestrictTeamInvite *string
RestrictPublicChannelManagement *string
RestrictPrivateChannelManagement *string
} }
type LdapSettings struct { type LdapSettings struct {
@@ -381,7 +383,17 @@ func (o *Config) SetDefaults() {
if o.TeamSettings.RestrictTeamInvite == nil { if o.TeamSettings.RestrictTeamInvite == nil {
o.TeamSettings.RestrictTeamInvite = new(string) 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 { if o.EmailSettings.EnableSignInWithEmail == nil {

Просмотреть файл

@@ -215,6 +215,8 @@ func getClientConfig(c *model.Config) map[string]string {
props["RestrictTeamNames"] = strconv.FormatBool(*c.TeamSettings.RestrictTeamNames) props["RestrictTeamNames"] = strconv.FormatBool(*c.TeamSettings.RestrictTeamNames)
props["RestrictDirectMessage"] = *c.TeamSettings.RestrictDirectMessage props["RestrictDirectMessage"] = *c.TeamSettings.RestrictDirectMessage
props["RestrictTeamInvite"] = *c.TeamSettings.RestrictTeamInvite props["RestrictTeamInvite"] = *c.TeamSettings.RestrictTeamInvite
props["RestrictPublicChannelManagement"] = *c.TeamSettings.RestrictPublicChannelManagement
props["RestrictPrivateChannelManagement"] = *c.TeamSettings.RestrictPrivateChannelManagement
props["EnableOAuthServiceProvider"] = strconv.FormatBool(c.ServiceSettings.EnableOAuthServiceProvider) props["EnableOAuthServiceProvider"] = strconv.FormatBool(c.ServiceSettings.EnableOAuthServiceProvider)
props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey

Просмотреть файл

@@ -21,12 +21,16 @@ export default class PolicySettings extends AdminSettings {
this.renderSettings = this.renderSettings.bind(this); this.renderSettings = this.renderSettings.bind(this);
this.state = Object.assign(this.state, { 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) { getConfigFromState(config) {
config.TeamSettings.RestrictTeamInvite = this.state.restrictTeamInvite; config.TeamSettings.RestrictTeamInvite = this.state.restrictTeamInvite;
config.TeamSettings.RestrictPublicChannelManagement = this.state.restrictPublicChannelManagement;
config.TeamSettings.RestrictPrivateChannelManagement = this.state.restrictPrivateChannelManagement;
return config; return config;
} }
@@ -48,9 +52,9 @@ export default class PolicySettings extends AdminSettings {
<DropdownSetting <DropdownSetting
id='restrictTeamInvite' id='restrictTeamInvite'
values={[ values={[
{value: Constants.TEAM_INVITE_ALL, text: Utils.localizeMessage('admin.general.policy.teamInviteAll', 'All team members')}, {value: Constants.PERMISSIONS_ALL, text: Utils.localizeMessage('admin.general.policy.permissionsAll', 'All team members')},
{value: Constants.TEAM_INVITE_TEAM_ADMIN, text: Utils.localizeMessage('admin.general.policy.teamInviteAdmin', 'Team and System Admins')}, {value: Constants.PERMISSIONS_TEAM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsAdmin', 'Team and System Admins')},
{value: Constants.TEAM_INVITE_SYSTEM_ADMIN, text: Utils.localizeMessage('admin.general.policy.teamInviteSystemAdmin', 'System Admins')} {value: Constants.PERMISSIONS_SYSTEM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsSystemAdmin', 'System Admins')}
]} ]}
label={ label={
<FormattedMessage <FormattedMessage
@@ -67,6 +71,50 @@ export default class PolicySettings extends AdminSettings {
/> />
} }
/> />
<DropdownSetting
id='restrictPublicChannelManagement'
values={[
{value: Constants.PERMISSIONS_ALL, text: Utils.localizeMessage('admin.general.policy.permissionsAll', 'All team members')},
{value: Constants.PERMISSIONS_TEAM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsAdmin', 'Team and System Admins')},
{value: Constants.PERMISSIONS_SYSTEM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsSystemAdmin', 'System Admins')}
]}
label={
<FormattedMessage
id='admin.general.policy.restrictPublicChannelManagementTitle'
defaultMessage='Enable public channel management permissions for:'
/>
}
value={this.state.restrictPublicChannelManagement}
onChange={this.handleChange}
helpText={
<FormattedHTMLMessage
id='admin.general.policy.restrictPublicChannelManagementDescription'
defaultMessage='Selecting "All team members" allows any team members to create, delete, rename, and set the header or purpose for public channels.<br/><br/>Selecting "Team and System Admins" restricts channel management permissions for public channels to Team and System Admins, including creating, deleting, renaming, and setting the channel header or purpose.<br/><br/>Selecting "System Admins" restricts channel management permissions for public channels to System Admins, including creating, deleting, renaming, and setting the channel header or purpose.'
/>
}
/>
<DropdownSetting
id='restrictPrivateChannelManagement'
values={[
{value: Constants.PERMISSIONS_ALL, text: Utils.localizeMessage('admin.general.policy.permissionsAll', 'All team members')},
{value: Constants.PERMISSIONS_TEAM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsAdmin', 'Team and System Admins')},
{value: Constants.PERMISSIONS_SYSTEM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsSystemAdmin', 'System Admins')}
]}
label={
<FormattedMessage
id='admin.general.policy.restrictPrivateChannelManagementTitle'
defaultMessage='Enable private group management permissions for:'
/>
}
value={this.state.restrictPrivateChannelManagement}
onChange={this.handleChange}
helpText={
<FormattedHTMLMessage
id='admin.general.policy.restrictPrivateChannelManagementDescription'
defaultMessage='Selecting "All team members" allows any team members to create, delete, rename, and set the header or purpose for private groups.<br/><br/>Selecting "Team and System Admins" restricts group management permissions for private groups to Team and System Admins, including creating, deleting, renaming, and setting the group header or purpose.<br/><br/>Selecting "System Admins" restricts group management permissions for private groups to System Admins, including creating, deleting, renaming, and setting the group header or purpose.'
/>
}
/>
</SettingsGroup> </SettingsGroup>
); );
} }

Просмотреть файл

@@ -56,6 +56,7 @@ export default class ChannelHeader extends React.Component {
state.showRenameChannelModal = false; state.showRenameChannelModal = false;
this.state = state; this.state = state;
} }
getStateFromStores() { getStateFromStores() {
const extraInfo = ChannelStore.getExtraInfo(this.props.channelId); const extraInfo = ChannelStore.getExtraInfo(this.props.channelId);
@@ -67,6 +68,7 @@ export default class ChannelHeader extends React.Component {
currentUser: UserStore.getCurrentUser() currentUser: UserStore.getCurrentUser()
}; };
} }
validState() { validState() {
if (!this.state.channel || if (!this.state.channel ||
!this.state.memberChannel || !this.state.memberChannel ||
@@ -77,6 +79,7 @@ export default class ChannelHeader extends React.Component {
} }
return true; return true;
} }
componentDidMount() { componentDidMount() {
ChannelStore.addChangeListener(this.onListenerChange); ChannelStore.addChangeListener(this.onListenerChange);
ChannelStore.addExtraInfoChangeListener(this.onListenerChange); ChannelStore.addExtraInfoChangeListener(this.onListenerChange);
@@ -87,6 +90,7 @@ export default class ChannelHeader extends React.Component {
$('.sidebar--left .dropdown-menu').perfectScrollbar(); $('.sidebar--left .dropdown-menu').perfectScrollbar();
document.addEventListener('keydown', this.openRecentMentions); document.addEventListener('keydown', this.openRecentMentions);
} }
componentWillUnmount() { componentWillUnmount() {
ChannelStore.removeChangeListener(this.onListenerChange); ChannelStore.removeChangeListener(this.onListenerChange);
ChannelStore.removeExtraInfoChangeListener(this.onListenerChange); ChannelStore.removeExtraInfoChangeListener(this.onListenerChange);
@@ -96,6 +100,7 @@ export default class ChannelHeader extends React.Component {
UserStore.removeStatusesChangeListener(this.onListenerChange); UserStore.removeStatusesChangeListener(this.onListenerChange);
document.removeEventListener('keydown', this.openRecentMentions); document.removeEventListener('keydown', this.openRecentMentions);
} }
onListenerChange() { onListenerChange() {
const newState = this.getStateFromStores(); const newState = this.getStateFromStores();
if (!Utils.areObjectsEqual(newState, this.state)) { if (!Utils.areObjectsEqual(newState, this.state)) {
@@ -103,6 +108,7 @@ export default class ChannelHeader extends React.Component {
} }
$('.channel-header__info .description').popover({placement: 'bottom', trigger: 'hover', html: true, delay: {show: 500, hide: 500}}); $('.channel-header__info .description').popover({placement: 'bottom', trigger: 'hover', html: true, delay: {show: 500, hide: 500}});
} }
handleLeave() { handleLeave() {
Client.leaveChannel(this.state.channel.id, Client.leaveChannel(this.state.channel.id,
() => { () => {
@@ -119,6 +125,7 @@ export default class ChannelHeader extends React.Component {
} }
); );
} }
searchMentions(e) { searchMentions(e) {
e.preventDefault(); e.preventDefault();
@@ -146,12 +153,14 @@ export default class ChannelHeader extends React.Component {
is_mention_search: true is_mention_search: true
}); });
} }
openRecentMentions(e) { openRecentMentions(e) {
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === Constants.KeyCodes.M) { if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === Constants.KeyCodes.M) {
e.preventDefault(); e.preventDefault();
this.searchMentions(e); this.searchMentions(e);
} }
} }
showRenameChannelModal(e) { showRenameChannelModal(e) {
e.preventDefault(); e.preventDefault();
@@ -159,6 +168,7 @@ export default class ChannelHeader extends React.Component {
showRenameChannelModal: true showRenameChannelModal: true
}); });
} }
hideRenameChannelModal() { hideRenameChannelModal() {
this.setState({ this.setState({
showRenameChannelModal: false showRenameChannelModal: false
@@ -179,6 +189,30 @@ export default class ChannelHeader extends React.Component {
return null; return null;
} }
showManagementOptions(channel, isAdmin, isSystemAdmin) {
if (global.window.mm_license.IsLicensed !== 'true') {
return true;
}
if (channel.type === Constants.OPEN_CHANNEL) {
if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
return false;
}
if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
return false;
}
} else if (channel.type === Constants.PRIVATE_CHANNEL) {
if (global.window.mm_config.RestrictPrivateChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
return false;
}
if (global.window.mm_config.RestrictPrivateChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
return false;
}
}
return true;
}
render() { render() {
if (!this.validState()) { if (!this.validState()) {
return null; return null;
@@ -210,7 +244,8 @@ export default class ChannelHeader extends React.Component {
); );
let channelTitle = channel.display_name; let channelTitle = channel.display_name;
const currentId = this.state.currentUser.id; const currentId = this.state.currentUser.id;
const isAdmin = Utils.isAdmin(this.state.memberChannel.roles) || TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser(); const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
const isDirect = (this.state.channel.type === 'D'); const isDirect = (this.state.channel.type === 'D');
if (isDirect) { if (isDirect) {
@@ -329,46 +364,6 @@ export default class ChannelHeader extends React.Component {
} }
} }
dropdownContents.push(
<li
key='set_channel_header'
role='presentation'
>
<ToggleModalButton
role='menuitem'
dialogType={EditChannelHeaderModal}
dialogProps={{channel}}
>
<FormattedMessage
id='channel_header.setHeader'
defaultMessage='Set {term} Header...'
values={{
term: (channelTerm)
}}
/>
</ToggleModalButton>
</li>
);
dropdownContents.push(
<li
key='set_channel_purpose'
role='presentation'
>
<a
role='menuitem'
href='#'
onClick={() => this.setState({showEditChannelPurposeModal: true})}
>
<FormattedMessage
id='channel_header.setPurpose'
defaultMessage='Set {term} Purpose...'
values={{
term: (channelTerm)
}}
/>
</a>
</li>
);
dropdownContents.push( dropdownContents.push(
<li <li
key='notification_preferences' key='notification_preferences'
@@ -391,7 +386,70 @@ export default class ChannelHeader extends React.Component {
</li> </li>
); );
if (isAdmin) { const deleteOption = (
<li
key='delete_channel'
role='presentation'
>
<ToggleModalButton
role='menuitem'
dialogType={DeleteChannelModal}
dialogProps={{channel}}
>
<FormattedMessage
id='channel_header.delete'
defaultMessage='Delete {term}...'
values={{
term: (channelTerm)
}}
/>
</ToggleModalButton>
</li>
);
if (this.showManagementOptions(channel, isAdmin, isSystemAdmin)) {
dropdownContents.push(
<li
key='set_channel_header'
role='presentation'
>
<ToggleModalButton
role='menuitem'
dialogType={EditChannelHeaderModal}
dialogProps={{channel}}
>
<FormattedMessage
id='channel_header.setHeader'
defaultMessage='Set {term} Header...'
values={{
term: (channelTerm)
}}
/>
</ToggleModalButton>
</li>
);
dropdownContents.push(
<li
key='set_channel_purpose'
role='presentation'
>
<a
role='menuitem'
href='#'
onClick={() => this.setState({showEditChannelPurposeModal: true})}
>
<FormattedMessage
id='channel_header.setPurpose'
defaultMessage='Set {term} Purpose...'
values={{
term: (channelTerm)
}}
/>
</a>
</li>
);
dropdownContents.push( dropdownContents.push(
<li <li
key='rename_channel' key='rename_channel'
@@ -414,27 +472,10 @@ export default class ChannelHeader extends React.Component {
); );
if (!ChannelStore.isDefault(channel)) { if (!ChannelStore.isDefault(channel)) {
dropdownContents.push( dropdownContents.push(deleteOption);
<li
key='delete_channel'
role='presentation'
>
<ToggleModalButton
role='menuitem'
dialogType={DeleteChannelModal}
dialogProps={{channel}}
>
<FormattedMessage
id='channel_header.delete'
defaultMessage='Delete {term}...'
values={{
term: (channelTerm)
}}
/>
</ToggleModalButton>
</li>
);
} }
} else if (this.state.userCount === 1) {
dropdownContents.push(deleteOption);
} }
const canLeave = channel.type === Constants.PRIVATE_CHANNEL ? this.state.userCount > 1 : true; const canLeave = channel.type === Constants.PRIVATE_CHANNEL ? this.state.userCount > 1 : true;

Просмотреть файл

@@ -6,8 +6,11 @@ import LoadingScreen from './loading_screen.jsx';
import NewChannelFlow from './new_channel_flow.jsx'; import NewChannelFlow from './new_channel_flow.jsx';
import ChannelStore from 'stores/channel_store.jsx'; import ChannelStore from 'stores/channel_store.jsx';
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import * as Utils from 'utils/utils.jsx'; import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
import * as AsyncClient from 'utils/async_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx';
import * as GlobalActions from 'actions/global_actions.jsx'; import * as GlobalActions from 'actions/global_actions.jsx';
@@ -132,6 +135,41 @@ export default class MoreChannels extends React.Component {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>; serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
} }
let createNewChannelButton = (
<button
type='button'
className='btn btn-primary channel-create-btn'
onClick={this.handleNewChannel}
>
<FormattedMessage
id='more_channels.create'
defaultMessage='Create New Channel'
/>
</button>
);
let createChannelHelpText = (
<p className='secondary-message'>
<FormattedMessage
id='more_channels.createClick'
defaultMessage="Click 'Create New Channel' to make a new one"
/>
</p>
);
const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
if (global.window.mm_license.IsLicensed === 'true') {
if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
createNewChannelButton = null;
createChannelHelpText = null;
} else if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
createNewChannelButton = null;
createChannelHelpText = null;
}
}
var moreChannels; var moreChannels;
if (this.state.channels != null) { if (this.state.channels != null) {
@@ -153,12 +191,7 @@ export default class MoreChannels extends React.Component {
defaultMessage='No more channels to join' defaultMessage='No more channels to join'
/> />
</p> </p>
<p className='secondary-message'> {createChannelHelpText}
<FormattedMessage
id='more_channels.createClick'
defaultMessage="Click 'Create New Channel' to make a new one"
/>
</p>
</div> </div>
); );
} }
@@ -195,16 +228,7 @@ export default class MoreChannels extends React.Component {
defaultMessage='More Channels' defaultMessage='More Channels'
/> />
</h4> </h4>
<button {createNewChannelButton}
type='button'
className='btn btn-primary channel-create-btn'
onClick={this.handleNewChannel}
>
<FormattedMessage
id='more_channels.create'
defaultMessage='Create New Channel'
/>
</button>
<NewChannelFlow <NewChannelFlow
show={this.state.showNewChannelModal} show={this.state.showNewChannelModal}
channelType={this.state.channelType} channelType={this.state.channelType}

Просмотреть файл

@@ -122,10 +122,10 @@ export default class NavbarDropdown extends React.Component {
} }
if (global.window.mm_license.IsLicensed === 'true') { if (global.window.mm_license.IsLicensed === 'true') {
if (global.window.mm_config.RestrictTeamInvite === Constants.TEAM_INVITE_SYSTEM_ADMIN && !isSystemAdmin) { if (global.window.mm_config.RestrictTeamInvite === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
teamLink = null; teamLink = null;
inviteLink = null; inviteLink = null;
} else if (global.window.mm_config.RestrictTeamInvite === Constants.TEAM_INVITE_TEAM_ADMIN && !isAdmin) { } else if (global.window.mm_config.RestrictTeamInvite === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
teamLink = null; teamLink = null;
inviteLink = null; inviteLink = null;
} }

Просмотреть файл

@@ -3,8 +3,12 @@
import $ from 'jquery'; import $ from 'jquery';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import * as Utils from 'utils/utils.jsx'; import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx'; import Constants from 'utils/constants.jsx';
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx'; import PreferenceStore from 'stores/preference_store.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl'; import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl';
@@ -113,6 +117,47 @@ class NewChannelModal extends React.Component {
serverError = <div className='form-group has-error'><p className='input__help error'>{this.props.serverError}</p></div>; serverError = <div className='form-group has-error'><p className='input__help error'>{this.props.serverError}</p></div>;
} }
let createPublicChannelLink = (
<a
href='#'
onClick={this.props.onTypeSwitched}
>
<FormattedMessage
id='channel_modal.publicChannel1'
defaultMessage='Create a public channel'
/>
</a>
);
let createPrivateChannelLink = (
<a
href='#'
onClick={this.props.onTypeSwitched}
>
<FormattedMessage
id='channel_modal.privateGroup2'
defaultMessage='Create a private group'
/>
</a>
);
const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
if (global.window.mm_license.IsLicensed === 'true') {
if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
createPublicChannelLink = null;
} else if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
createPublicChannelLink = null;
}
if (global.window.mm_config.RestrictPrivateChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
createPrivateChannelLink = null;
} else if (global.window.mm_config.RestrictPrivateChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
createPrivateChannelLink = null;
}
}
var channelTerm = ''; var channelTerm = '';
var channelSwitchText = ''; var channelSwitchText = '';
switch (this.props.channelType) { switch (this.props.channelType) {
@@ -129,15 +174,7 @@ class NewChannelModal extends React.Component {
id='channel_modal.privateGroup1' id='channel_modal.privateGroup1'
defaultMessage='Create a new private group with restricted membership. ' defaultMessage='Create a new private group with restricted membership. '
/> />
<a {createPublicChannelLink}
href='#'
onClick={this.props.onTypeSwitched}
>
<FormattedMessage
id='channel_modal.publicChannel1'
defaultMessage='Create a public channel'
/>
</a>
</div> </div>
); );
break; break;
@@ -154,15 +191,7 @@ class NewChannelModal extends React.Component {
id='channel_modal.publicChannel2' id='channel_modal.publicChannel2'
defaultMessage='Create a new public channel anyone can join. ' defaultMessage='Create a new public channel anyone can join. '
/> />
<a {createPrivateChannelLink}
href='#'
onClick={this.props.onTypeSwitched}
>
<FormattedMessage
id='channel_modal.privateGroup2'
defaultMessage='Create a private group'
/>
</a>
</div> </div>
); );
break; break;

Просмотреть файл

@@ -682,6 +682,55 @@ export default class Sidebar extends React.Component {
/> />
); );
const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
let createPublicChannelIcon = (
<OverlayTrigger
delayShow={500}
placement='top'
overlay={createChannelTootlip}
>
<a
className='add-channel-btn'
href='#'
onClick={this.showNewChannelModal.bind(this, Constants.OPEN_CHANNEL)}
>
{'+'}
</a>
</OverlayTrigger>
);
let createPrivateChannelIcon = (
<OverlayTrigger
delayShow={500}
placement='top'
overlay={createGroupTootlip}
>
<a
className='add-channel-btn'
href='#'
onClick={this.showNewChannelModal.bind(this, Constants.PRIVATE_CHANNEL)}
>
{'+'}
</a>
</OverlayTrigger>
);
if (global.window.mm_license.IsLicensed === 'true') {
if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
createPublicChannelIcon = null;
} else if (global.window.mm_config.RestrictPublicChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
createPublicChannelIcon = null;
}
if (global.window.mm_config.RestrictPrivateChannelManagement === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
createPrivateChannelIcon = null;
} else if (global.window.mm_config.RestrictPrivateChannelManagement === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
createPrivateChannelIcon = null;
}
}
return ( return (
<div <div
className='sidebar--left' className='sidebar--left'
@@ -728,19 +777,7 @@ export default class Sidebar extends React.Component {
id='sidebar.channels' id='sidebar.channels'
defaultMessage='Channels' defaultMessage='Channels'
/> />
<OverlayTrigger {createPublicChannelIcon}
delayShow={500}
placement='top'
overlay={createChannelTootlip}
>
<a
className='add-channel-btn'
href='#'
onClick={this.showNewChannelModal.bind(this, 'O')}
>
{'+'}
</a>
</OverlayTrigger>
</h4> </h4>
</li> </li>
{publicChannelItems} {publicChannelItems}
@@ -765,19 +802,7 @@ export default class Sidebar extends React.Component {
id='sidebar.pg' id='sidebar.pg'
defaultMessage='Private Groups' defaultMessage='Private Groups'
/> />
<OverlayTrigger {createPrivateChannelIcon}
delayShow={500}
placement='top'
overlay={createGroupTootlip}
>
<a
className='add-channel-btn'
href='#'
onClick={this.showNewChannelModal.bind(this, 'P')}
>
{'+'}
</a>
</OverlayTrigger>
</h4> </h4>
</li> </li>
{privateChannelItems} {privateChannelItems}

Просмотреть файл

@@ -186,10 +186,10 @@ export default class SidebarRightMenu extends React.Component {
} }
if (global.window.mm_license.IsLicensed === 'true') { if (global.window.mm_license.IsLicensed === 'true') {
if (global.window.mm_config.RestrictTeamInvite === Constants.TEAM_INVITE_SYSTEM_ADMIN && !isSystemAdmin) { if (global.window.mm_config.RestrictTeamInvite === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
teamLink = null; teamLink = null;
inviteLink = null; inviteLink = null;
} else if (global.window.mm_config.RestrictTeamInvite === Constants.TEAM_INVITE_TEAM_ADMIN && !isAdmin) { } else if (global.window.mm_config.RestrictTeamInvite === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
teamLink = null; teamLink = null;
inviteLink = null; inviteLink = null;
} }

Просмотреть файл

@@ -108,7 +108,7 @@ export default class TutorialIntroScreens extends React.Component {
let inviteModalLink; let inviteModalLink;
let inviteText; let inviteText;
if (global.window.mm_license.IsLicensed !== 'true' || global.window.mm_config.RestrictTeamInvite === Constants.TEAM_INVITE_ALL) { if (global.window.mm_license.IsLicensed !== 'true' || global.window.mm_config.RestrictTeamInvite === Constants.PERMISSIONS_ALL) {
if (team.type === Constants.INVITE_TEAM) { if (team.type === Constants.INVITE_TEAM) {
inviteModalLink = ( inviteModalLink = (
<a <a

Просмотреть файл

@@ -233,11 +233,15 @@
"admin.general.localization.serverLocaleTitle": "Default Server Language:", "admin.general.localization.serverLocaleTitle": "Default Server Language:",
"admin.general.log": "Logging", "admin.general.log": "Logging",
"admin.general.policy": "Policy", "admin.general.policy": "Policy",
"admin.general.policy.teamInviteAdmin": "Team and System Admins", "admin.general.policy.permissionsAll": "All team members",
"admin.general.policy.teamInviteAll": "All team members", "admin.general.policy.permissionsAdmin": "Team and System Admins",
"admin.general.policy.teamInviteDescription": "Selecting \"All team members\" allows any team member to invite others using an email invitation or team invite link.<br/><br/>Selecting \"Team and System Admins\" hides the email invitation and team invite link in the Main Menu from users who are not Team or System Admins. Note: If \"Get Team Invite Link\" is used to share a link, it will need to be regenerated after the desired users joined the team.<br/><br/>Selecting \"System Admins\" hides the email invitation and team invite link in the Main Menu from users who are not System Admins. Note: If \"Get Team Invite Link\" is used to share a link, it will need to be regenerated after the desired users joined the team.", "admin.general.policy.permissionsSystemAdmin": "System Admins",
"admin.general.policy.teamInviteSystemAdmin": "System Admins",
"admin.general.policy.teamInviteTitle": "Enable sending team invites from:", "admin.general.policy.teamInviteTitle": "Enable sending team invites from:",
"admin.general.policy.teamInviteDescription": "Selecting \"All team members\" allows any team member to invite others using an email invitation or team invite link.<br/><br/>Selecting \"Team and System Admins\" hides the email invitation and team invite link in the Main Menu from users who are not Team or System Admins. Note: If \"Get Team Invite Link\" is used to share a link, it will need to be regenerated after the desired users joined the team.<br/><br/>Selecting \"System Admins\" hides the email invitation and team invite link in the Main Menu from users who are not System Admins. Note: If \"Get Team Invite Link\" is used to share a link, it will need to be regenerated after the desired users joined the team.",
"admin.general.policy.restrictPublicChannelManagementTitle": "Enable public channel management permissions for:",
"admin.general.policy.restrictPublicChannelManagementDescription": "Selecting \"All team members\" allows any team members to create, delete, rename, and set the header or purpose for public channels.<br/><br/>Selecting \"Team and System Admins\" restricts channel management permissions for public channels to Team and System Admins, including creating, deleting, renaming, and setting the channel header or purpose.<br/><br/>Selecting \"System Admins\" restricts channel management permissions for public channels to System Admins, including creating, deleting, renaming, and setting the channel header or purpose.",
"admin.general.policy.restrictPrivateChannelManagementTitle": "Enable private group management permissions for:",
"admin.general.policy.restrictPrivateChannelManagementDescription": "Selecting \"All team members\" allows any team members to create, delete, rename, and set the header or purpose for private groups.<br/><br/>Selecting \"Team and System Admins\" restricts group management permissions for private groups to Team and System Admins, including creating, deleting, renaming, and setting the group header or purpose.<br/><br/>Selecting \"System Admins\" restricts group management permissions for private groups to System Admins, including creating, deleting, renaming, and setting the group header or purpose.",
"admin.general.privacy": "Privacy", "admin.general.privacy": "Privacy",
"admin.general.usersAndTeams": "Users and Teams", "admin.general.usersAndTeams": "Users and Teams",
"admin.gitab.clientSecretDescription": "Obtain this value via the instructions above for logging into GitLab.", "admin.gitab.clientSecretDescription": "Obtain this value via the instructions above for logging into GitLab.",

Просмотреть файл

@@ -53,54 +53,70 @@ class ChannelStoreClass extends EventEmitter {
this.extraInfos = {}; this.extraInfos = {};
this.unreadCounts = {}; this.unreadCounts = {};
} }
get POST_MODE_CHANNEL() { get POST_MODE_CHANNEL() {
return 1; return 1;
} }
get POST_MODE_FOCUS() { get POST_MODE_FOCUS() {
return 2; return 2;
} }
emitChange() { emitChange() {
this.emit(CHANGE_EVENT); this.emit(CHANGE_EVENT);
} }
addChangeListener(callback) { addChangeListener(callback) {
this.on(CHANGE_EVENT, callback); this.on(CHANGE_EVENT, callback);
} }
removeChangeListener(callback) { removeChangeListener(callback) {
this.removeListener(CHANGE_EVENT, callback); this.removeListener(CHANGE_EVENT, callback);
} }
emitMoreChange() { emitMoreChange() {
this.emit(MORE_CHANGE_EVENT); this.emit(MORE_CHANGE_EVENT);
} }
addMoreChangeListener(callback) { addMoreChangeListener(callback) {
this.on(MORE_CHANGE_EVENT, callback); this.on(MORE_CHANGE_EVENT, callback);
} }
removeMoreChangeListener(callback) { removeMoreChangeListener(callback) {
this.removeListener(MORE_CHANGE_EVENT, callback); this.removeListener(MORE_CHANGE_EVENT, callback);
} }
emitExtraInfoChange() { emitExtraInfoChange() {
this.emit(EXTRA_INFO_EVENT); this.emit(EXTRA_INFO_EVENT);
} }
addExtraInfoChangeListener(callback) { addExtraInfoChangeListener(callback) {
this.on(EXTRA_INFO_EVENT, callback); this.on(EXTRA_INFO_EVENT, callback);
} }
removeExtraInfoChangeListener(callback) { removeExtraInfoChangeListener(callback) {
this.removeListener(EXTRA_INFO_EVENT, callback); this.removeListener(EXTRA_INFO_EVENT, callback);
} }
emitLeave(id) { emitLeave(id) {
this.emit(LEAVE_EVENT, id); this.emit(LEAVE_EVENT, id);
} }
addLeaveListener(callback) { addLeaveListener(callback) {
this.on(LEAVE_EVENT, callback); this.on(LEAVE_EVENT, callback);
} }
removeLeaveListener(callback) { removeLeaveListener(callback) {
this.removeListener(LEAVE_EVENT, callback); this.removeListener(LEAVE_EVENT, callback);
} }
findFirstBy(field, value) { findFirstBy(field, value) {
return this.doFindFirst(field, value, this.getChannels()); return this.doFindFirst(field, value, this.getChannels());
} }
findFirstMoreBy(field, value) { findFirstMoreBy(field, value) {
return this.doFindFirst(field, value, this.getMoreChannels()); return this.doFindFirst(field, value, this.getMoreChannels());
} }
doFindFirst(field, value, channels) { doFindFirst(field, value, channels) {
for (var i = 0; i < channels.length; i++) { for (var i = 0; i < channels.length; i++) {
if (channels[i][field] === value) { if (channels[i][field] === value) {
@@ -110,33 +126,43 @@ class ChannelStoreClass extends EventEmitter {
return null; return null;
} }
get(id) { get(id) {
return this.findFirstBy('id', id); return this.findFirstBy('id', id);
} }
getMember(id) { getMember(id) {
return this.getAllMembers()[id]; return this.getAllMembers()[id];
} }
getByName(name) { getByName(name) {
return this.findFirstBy('name', name); return this.findFirstBy('name', name);
} }
getByDisplayName(displayName) { getByDisplayName(displayName) {
return this.findFirstBy('display_name', displayName); return this.findFirstBy('display_name', displayName);
} }
getMoreByName(name) { getMoreByName(name) {
return this.findFirstMoreBy('name', name); return this.findFirstMoreBy('name', name);
} }
getAll() { getAll() {
return this.getChannels(); return this.getChannels();
} }
getAllMembers() { getAllMembers() {
return this.getChannelMembers(); return this.getChannelMembers();
} }
getMoreAll() { getMoreAll() {
return this.getMoreChannels(); return this.getMoreChannels();
} }
setCurrentId(id) { setCurrentId(id) {
this.currentId = id; this.currentId = id;
} }
resetCounts(id) { resetCounts(id) {
const cm = this.channelMembers; const cm = this.channelMembers;
for (var cmid in cm) { for (var cmid in cm) {
@@ -151,9 +177,11 @@ class ChannelStoreClass extends EventEmitter {
} }
} }
} }
getCurrentId() { getCurrentId() {
return this.currentId; return this.currentId;
} }
getCurrent() { getCurrent() {
var currentId = this.getCurrentId(); var currentId = this.getCurrentId();
@@ -163,6 +191,7 @@ class ChannelStoreClass extends EventEmitter {
return null; return null;
} }
getCurrentMember() { getCurrentMember() {
var currentId = this.getCurrentId(); var currentId = this.getCurrentId();
@@ -172,15 +201,18 @@ class ChannelStoreClass extends EventEmitter {
return null; return null;
} }
setChannelMember(member) { setChannelMember(member) {
var members = this.getChannelMembers(); var members = this.getChannelMembers();
members[member.channel_id] = member; members[member.channel_id] = member;
this.storeChannelMembers(members); this.storeChannelMembers(members);
this.emitChange(); this.emitChange();
} }
getCurrentExtraInfo() { getCurrentExtraInfo() {
return this.getExtraInfo(this.getCurrentId()); return this.getExtraInfo(this.getCurrentId());
} }
getExtraInfo(channelId) { getExtraInfo(channelId) {
var extra = null; var extra = null;
@@ -197,6 +229,7 @@ class ChannelStoreClass extends EventEmitter {
return extra; return extra;
} }
pStoreChannel(channel) { pStoreChannel(channel) {
var channels = this.getChannels(); var channels = this.getChannels();
var found; var found;
@@ -220,35 +253,45 @@ class ChannelStoreClass extends EventEmitter {
channels.sort(Utils.sortByDisplayName); channels.sort(Utils.sortByDisplayName);
this.storeChannels(channels); this.storeChannels(channels);
} }
storeChannels(channels) { storeChannels(channels) {
this.channels = channels; this.channels = channels;
} }
getChannels() { getChannels() {
return this.channels; return this.channels;
} }
pStoreChannelMember(channelMember) { pStoreChannelMember(channelMember) {
var members = this.getChannelMembers(); var members = this.getChannelMembers();
members[channelMember.channel_id] = channelMember; members[channelMember.channel_id] = channelMember;
this.storeChannelMembers(members); this.storeChannelMembers(members);
} }
storeChannelMembers(channelMembers) { storeChannelMembers(channelMembers) {
this.channelMembers = channelMembers; this.channelMembers = channelMembers;
} }
getChannelMembers() { getChannelMembers() {
return this.channelMembers; return this.channelMembers;
} }
storeMoreChannels(channels) { storeMoreChannels(channels) {
this.moreChannels = channels; this.moreChannels = channels;
} }
getMoreChannels() { getMoreChannels() {
return this.moreChannels; return this.moreChannels;
} }
storeExtraInfos(extraInfos) { storeExtraInfos(extraInfos) {
this.extraInfos = extraInfos; this.extraInfos = extraInfos;
} }
getExtraInfos() { getExtraInfos() {
return this.extraInfos; return this.extraInfos;
} }
isDefault(channel) { isDefault(channel) {
return channel.name === Constants.DEFAULT_CHANNEL; return channel.name === Constants.DEFAULT_CHANNEL;
} }

Просмотреть файл

@@ -114,9 +114,9 @@ export function createDefaultIntroMessage(channel) {
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser(); const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
if (global.window.mm_license.IsLicensed === 'true') { if (global.window.mm_license.IsLicensed === 'true') {
if (global.window.mm_config.RestrictTeamInvite === Constants.TEAM_INVITE_SYSTEM_ADMIN && !isSystemAdmin) { if (global.window.mm_config.RestrictTeamInvite === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
inviteModalLink = null; inviteModalLink = null;
} else if (global.window.mm_config.RestrictTeamInvite === Constants.TEAM_INVITE_TEAM_ADMIN && !isAdmin) { } else if (global.window.mm_config.RestrictTeamInvite === Constants.PERMISSIONS_TEAM_ADMIN && !isAdmin) {
inviteModalLink = null; inviteModalLink = null;
} }
} }

Просмотреть файл

@@ -762,7 +762,7 @@ export default {
POST_COLLAPSE_TIMEOUT: 1000 * 60 * 5, // five minutes POST_COLLAPSE_TIMEOUT: 1000 * 60 * 5, // five minutes
LICENSE_EXPIRY_NOTIFICATION: 1000 * 60 * 60 * 24 * 15, // 15 days LICENSE_EXPIRY_NOTIFICATION: 1000 * 60 * 60 * 24 * 15, // 15 days
LICENSE_GRACE_PERIOD: 1000 * 60 * 60 * 24 * 15, // 15 days LICENSE_GRACE_PERIOD: 1000 * 60 * 60 * 24 * 15, // 15 days
TEAM_INVITE_ALL: 'all', PERMISSIONS_ALL: 'all',
TEAM_INVITE_TEAM_ADMIN: 'team_admin', PERMISSIONS_TEAM_ADMIN: 'team_admin',
TEAM_INVITE_SYSTEM_ADMIN: 'system_admin' PERMISSIONS_SYSTEM_ADMIN: 'system_admin'
}; };