diff --git a/api4/channel.go b/api4/channel.go index 41e6616b9a..2032ba29b4 100644 --- a/api4/channel.go +++ b/api4/channel.go @@ -238,8 +238,8 @@ func convertChannelToPrivate(c *Context, w http.ResponseWriter, r *http.Request) defer c.LogAuditRec(auditRec) auditRec.AddMeta("channel", oldPublicChannel) - if !c.App.SessionHasPermissionToTeam(*c.App.Session(), oldPublicChannel.TeamId, model.PERMISSION_MANAGE_TEAM) { - c.SetPermissionError(model.PERMISSION_MANAGE_TEAM) + if !c.App.SessionHasPermissionToChannel(*c.App.Session(), c.Params.ChannelId, model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE) { + c.SetPermissionError(model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE) return } @@ -298,8 +298,13 @@ func updateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("channel", channel) auditRec.AddMeta("new_type", privacy) - if !c.App.SessionHasPermissionToTeam(*c.App.Session(), channel.TeamId, model.PERMISSION_MANAGE_TEAM) { - c.SetPermissionError(model.PERMISSION_MANAGE_TEAM) + if privacy == model.CHANNEL_OPEN && !c.App.SessionHasPermissionToChannel(*c.App.Session(), c.Params.ChannelId, model.PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC) { + c.SetPermissionError(model.PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC) + return + } + + if privacy == model.CHANNEL_PRIVATE && !c.App.SessionHasPermissionToChannel(*c.App.Session(), c.Params.ChannelId, model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE) { + c.SetPermissionError(model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE) return } diff --git a/api4/channel_test.go b/api4/channel_test.go index 4666c60ed1..a1cd943caa 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -1686,6 +1686,13 @@ func TestConvertChannelToPrivate(t *testing.T) { CheckForbiddenStatus(t, resp) th.LoginTeamAdmin() + th.RemovePermissionFromRole(model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, model.TEAM_ADMIN_ROLE_ID) + + _, resp = Client.ConvertChannelToPrivate(publicChannel.Id) + CheckForbiddenStatus(t, resp) + + th.AddPermissionToRole(model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, model.TEAM_ADMIN_ROLE_ID) + rchannel, resp := Client.ConvertChannelToPrivate(publicChannel.Id) CheckOKStatus(t, resp) require.Equal(t, model.CHANNEL_PRIVATE, rchannel.Type, "channel should be converted from public to private") @@ -1790,6 +1797,25 @@ func TestUpdateChannelPrivacy(t *testing.T) { assert.Equal(t, tc.expectedPrivacy, updatedChannel.Type) }) } + + t.Run("Enforces convert channel permissions", func(t *testing.T) { + th.RemovePermissionFromRole(model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, model.TEAM_ADMIN_ROLE_ID) + th.RemovePermissionFromRole(model.PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC.Id, model.TEAM_ADMIN_ROLE_ID) + + _, resp := Client.UpdateChannelPrivacy(publicChannel.Id, model.CHANNEL_PRIVATE) + CheckForbiddenStatus(t, resp) + _, resp = Client.UpdateChannelPrivacy(privateChannel.Id, model.CHANNEL_OPEN) + CheckForbiddenStatus(t, resp) + + th.AddPermissionToRole(model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, model.TEAM_ADMIN_ROLE_ID) + th.AddPermissionToRole(model.PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC.Id, model.TEAM_ADMIN_ROLE_ID) + + _, resp = Client.UpdateChannelPrivacy(privateChannel.Id, model.CHANNEL_OPEN) + CheckNoError(t, resp) + _, resp = Client.UpdateChannelPrivacy(publicChannel.Id, model.CHANNEL_PRIVATE) + CheckNoError(t, resp) + }) + } func TestRestoreChannel(t *testing.T) { diff --git a/app/app_test.go b/app/app_test.go index 3b3819e03d..1b7b61c31a 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -152,6 +152,8 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) { model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id, model.PERMISSION_MANAGE_INCOMING_WEBHOOKS.Id, model.PERMISSION_MANAGE_OUTGOING_WEBHOOKS.Id, + model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, + model.PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC.Id, model.PERMISSION_DELETE_POST.Id, model.PERMISSION_DELETE_OTHERS_POSTS.Id, }, @@ -277,6 +279,8 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) { model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id, model.PERMISSION_MANAGE_INCOMING_WEBHOOKS.Id, model.PERMISSION_MANAGE_OUTGOING_WEBHOOKS.Id, + model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, + model.PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.PERMISSION_DELETE_POST.Id, @@ -429,6 +433,8 @@ func TestDoEmojisPermissionsMigration(t *testing.T) { model.PERMISSION_REMOVE_REACTION.Id, model.PERMISSION_USE_CHANNEL_MENTIONS.Id, model.PERMISSION_USE_GROUP_MENTIONS.Id, + model.PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, + model.PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC.Id, } sort.Strings(expected2) sort.Strings(role2.Permissions) diff --git a/app/permissions_migrations.go b/app/permissions_migrations.go index 8291e84a5a..4bdf2a019d 100644 --- a/app/permissions_migrations.go +++ b/app/permissions_migrations.go @@ -21,6 +21,7 @@ type permissionsMap []permissionTransformation const ( PERMISSION_MANAGE_SYSTEM = "manage_system" + PERMISSION_MANAGE_TEAM = "manage_team" PERMISSION_MANAGE_EMOJIS = "manage_emojis" PERMISSION_MANAGE_OTHERS_EMOJIS = "manage_others_emojis" PERMISSION_CREATE_EMOJIS = "create_emojis" @@ -46,6 +47,8 @@ const ( PERMISSION_DELETE_PRIVATE_CHANNEL = "delete_private_channel" PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = "manage_public_channel_properties" PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES = "manage_private_channel_properties" + PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE = "convert_public_channel_to_private" + PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC = "convert_private_channel_to_public" PERMISSION_VIEW_MEMBERS = "view_members" PERMISSION_INVITE_USER = "invite_user" PERMISSION_INVITE_GUEST = "invite_guest" @@ -489,6 +492,15 @@ func (a *App) getAddSystemConsolePermissionsMigration() (permissionsMap, error) return transformations, nil } +func (a *App) getAddConvertChannelPermissionsMigration() (permissionsMap, error) { + return permissionsMap{ + permissionTransformation{ + On: permissionExists(PERMISSION_MANAGE_TEAM), + Add: []string{PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE, PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC}, + }, + }, nil +} + // DoPermissionsMigrations execute all the permissions migrations need by the current version. func (a *App) DoPermissionsMigrations() error { PermissionsMigrations := []struct { @@ -507,6 +519,7 @@ func (a *App) DoPermissionsMigrations() error { {Key: model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS, Migration: a.channelModerationPermissionsMigration}, {Key: model.MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION, Migration: a.getAddUseGroupMentionsPermissionMigration}, {Key: model.MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS, Migration: a.getAddSystemConsolePermissionsMigration}, + {Key: model.MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS, Migration: a.getAddConvertChannelPermissionsMigration}, } for _, migration := range PermissionsMigrations { diff --git a/model/migration.go b/model/migration.go index f0e24659ad..1bcfdb0e94 100644 --- a/model/migration.go +++ b/model/migration.go @@ -19,4 +19,5 @@ const ( MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION = "add_use_group_mentions_permission" MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS = "add_system_console_permissions" MIGRATION_KEY_SIDEBAR_CATEGORIES_PHASE_2 = "migration_sidebar_categories_phase_2" + MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS = "add_convert_channel_permissions" ) diff --git a/model/permission.go b/model/permission.go index dca3c6eddb..cf05c28145 100644 --- a/model/permission.go +++ b/model/permission.go @@ -25,6 +25,8 @@ var PERMISSION_CREATE_PUBLIC_CHANNEL *Permission var PERMISSION_CREATE_PRIVATE_CHANNEL *Permission var PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS *Permission var PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS *Permission +var PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE *Permission +var PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC *Permission var PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE *Permission var PERMISSION_MANAGE_ROLES *Permission var PERMISSION_MANAGE_TEAM_ROLES *Permission @@ -209,6 +211,18 @@ func initializePermissions() { "authentication.permissions.manage_private_channel_members.description", PermissionScopeChannel, } + PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE = &Permission{ + "convert_public_channel_to_private", + "authentication.permissions.convert_public_channel_to_private.name", + "authentication.permissions.convert_public_channel_to_private.description", + PermissionScopeChannel, + } + PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC = &Permission{ + "convert_private_channel_to_public", + "authentication.permissions.convert_private_channel_to_public.name", + "authentication.permissions.convert_private_channel_to_public.description", + PermissionScopeChannel, + } PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE = &Permission{ "assign_system_admin_role", "authentication.permissions.assign_system_admin_role.name", @@ -933,6 +947,8 @@ func initializePermissions() { PERMISSION_MANAGE_CHANNEL_ROLES, PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES, PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES, + PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE, + PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC, PERMISSION_DELETE_PUBLIC_CHANNEL, PERMISSION_DELETE_PRIVATE_CHANNEL, PERMISSION_READ_CHANNEL, diff --git a/model/role.go b/model/role.go index c61936cc00..5a8e923f45 100644 --- a/model/role.go +++ b/model/role.go @@ -73,6 +73,8 @@ func init() { PERMISSION_DELETE_PRIVATE_CHANNEL, PERMISSION_DELETE_PUBLIC_CHANNEL, PERMISSION_MANAGE_CHANNEL_ROLES, + PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE, + PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC, }, PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_TEAMS.Id: { PERMISSION_MANAGE_TEAM_ROLES, @@ -85,6 +87,8 @@ func init() { PERMISSION_MANAGE_TEAM, PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS, PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS, + PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE, + PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC, }, PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT.Id: { PERMISSION_MANAGE_JOBS, @@ -576,6 +580,8 @@ func MakeDefaultRoles() map[string]*Role { PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id, PERMISSION_MANAGE_INCOMING_WEBHOOKS.Id, PERMISSION_MANAGE_OUTGOING_WEBHOOKS.Id, + PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE.Id, + PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC.Id, }, SchemeManaged: true, BuiltIn: true, diff --git a/testlib/store.go b/testlib/store.go index 12685256cd..5e60c705af 100644 --- a/testlib/store.go +++ b/testlib/store.go @@ -45,6 +45,7 @@ func GetMockStoreForSetupFunctions() *mocks.Store { systemStore.On("GetByName", model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_CHANNEL_MODERATIONS_PERMISSIONS, Value: "true"}, nil) systemStore.On("GetByName", model.MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION).Return(&model.System{Name: model.MIGRATION_KEY_ADD_USE_GROUP_MENTIONS_PERMISSION, Value: "true"}, nil) systemStore.On("GetByName", model.MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS, Value: "true"}, nil) + systemStore.On("GetByName", model.MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS, Value: "true"}, nil) systemStore.On("Get").Return(make(model.StringMap), nil) systemStore.On("Save", mock.AnythingOfType("*model.System")).Return(nil)