summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/apitestlib.go112
-rw-r--r--api/channel_test.go728
-rw-r--r--api/oauth_test.go44
-rw-r--r--api/post_test.go59
-rw-r--r--api/team.go12
-rw-r--r--api/team_test.go100
-rw-r--r--api/webhook_test.go143
-rw-r--r--api4/api.go5
-rw-r--r--api4/apitestlib.go112
-rw-r--r--api4/channel.go1
-rw-r--r--api4/channel_test.go451
-rw-r--r--api4/context.go23
-rw-r--r--api4/oauth_test.go100
-rw-r--r--api4/params.go10
-rw-r--r--api4/post_test.go7
-rw-r--r--api4/role.go100
-rw-r--r--api4/role_test.go184
-rw-r--r--api4/team_test.go127
-rw-r--r--api4/webhook_test.go72
-rw-r--r--app/app.go60
-rw-r--r--app/app_test.go340
-rw-r--r--app/apptestlib.go52
-rw-r--r--app/authorization.go44
-rw-r--r--app/authorization_test.go6
-rw-r--r--app/channel.go4
-rw-r--r--app/import_test.go16
-rw-r--r--app/post.go2
-rw-r--r--app/role.go88
-rw-r--r--app/team.go4
-rw-r--r--app/user.go4
-rw-r--r--cmd/platform/server.go2
-rw-r--r--i18n/en.json28
-rw-r--r--model/client4.go46
-rw-r--r--model/cluster_message.go1
-rw-r--r--model/permission.go (renamed from model/authorization.go)318
-rw-r--r--model/permission_test.go18
-rw-r--r--model/role.go310
-rw-r--r--model/user.go7
-rw-r--r--model/user_test.go4
-rw-r--r--model/websocket_message.go1
-rw-r--r--store/layered_store.go34
-rw-r--r--store/layered_store_supplier.go6
-rw-r--r--store/local_cache_supplier.go8
-rw-r--r--store/local_cache_supplier_roles.go68
-rw-r--r--store/redis_supplier.go20
-rw-r--r--store/sqlstore/role_store_test.go14
-rw-r--r--store/sqlstore/role_supplier.go163
-rw-r--r--store/sqlstore/store.go1
-rw-r--r--store/sqlstore/supplier.go6
-rw-r--r--store/store.go8
-rw-r--r--store/storetest/mocks/LayeredStoreDatabaseLayer.go108
-rw-r--r--store/storetest/mocks/LayeredStoreSupplier.go92
-rw-r--r--store/storetest/mocks/RoleStore.go78
-rw-r--r--store/storetest/mocks/SqlStore.go16
-rw-r--r--store/storetest/mocks/Store.go16
-rw-r--r--store/storetest/role_store.go244
-rw-r--r--store/storetest/store.go3
-rw-r--r--utils/authorization.go18
-rw-r--r--web/web_test.go2
59 files changed, 2949 insertions, 1701 deletions
diff --git a/api/apitestlib.go b/api/apitestlib.go
index 8d7f54902..f53e7b237 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -111,6 +111,7 @@ func setupTestHelper(enterprise bool) *TestHelper {
Init(th.App, th.App.Srv.Router)
wsapi.Init(th.App, th.App.Srv.WebSocketRouter)
th.App.Srv.Store.MarkSystemRanUnitTests()
+ th.App.DoAdvancedPermissionsMigration()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
@@ -389,3 +390,114 @@ func (me *TestHelper) TearDown() {
panic(err)
}
}
+
+func (me *TestHelper) SaveDefaultRolePermissions() map[string][]string {
+ utils.DisableDebugLogForTest()
+
+ results := make(map[string][]string)
+
+ for _, roleName := range []string{
+ "system_user",
+ "system_admin",
+ "team_user",
+ "team_admin",
+ "channel_user",
+ "channel_admin",
+ } {
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ results[roleName] = role.Permissions
+ }
+
+ utils.EnableDebugLogForTest()
+ return results
+}
+
+func (me *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
+ utils.DisableDebugLogForTest()
+
+ for roleName, permissions := range data {
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ if strings.Join(role.Permissions, " ") == strings.Join(permissions, " ") {
+ continue
+ }
+
+ role.Permissions = permissions
+
+ _, err2 := me.App.UpdateRole(role)
+ if err2 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err2)
+ }
+ }
+
+ utils.EnableDebugLogForTest()
+}
+
+func (me *TestHelper) RemovePermissionFromRole(permission string, roleName string) {
+ utils.DisableDebugLogForTest()
+
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ var newPermissions []string
+ for _, p := range role.Permissions {
+ if p != permission {
+ newPermissions = append(newPermissions, p)
+ }
+ }
+
+ if strings.Join(role.Permissions, " ") == strings.Join(newPermissions, " ") {
+ utils.EnableDebugLogForTest()
+ return
+ }
+
+ role.Permissions = newPermissions
+
+ _, err2 := me.App.UpdateRole(role)
+ if err2 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err2)
+ }
+
+ utils.EnableDebugLogForTest()
+}
+
+func (me *TestHelper) AddPermissionToRole(permission string, roleName string) {
+ utils.DisableDebugLogForTest()
+
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ for _, existingPermission := range role.Permissions {
+ if existingPermission == permission {
+ utils.EnableDebugLogForTest()
+ return
+ }
+ }
+
+ role.Permissions = append(role.Permissions, permission)
+
+ _, err2 := me.App.UpdateRole(role)
+ if err2 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err2)
+ }
+
+ utils.EnableDebugLogForTest()
+}
diff --git a/api/channel_test.go b/api/channel_test.go
index 5533105c3..37dde24bd 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -12,7 +12,6 @@ import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store"
"github.com/mattermost/mattermost-server/store/sqlstore"
- "github.com/mattermost/mattermost-server/utils"
)
func TestCreateChannel(t *testing.T) {
@@ -20,7 +19,6 @@ func TestCreateChannel(t *testing.T) {
defer th.TearDown()
Client := th.BasicClient
- SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam
th.LoginBasic2()
team2 := th.CreateTeam(th.BasicClient)
@@ -97,23 +95,14 @@ func TestCreateChannel(t *testing.T) {
t.Fatal("Should have errored out on direct channel type")
}
- isLicensed := utils.IsLicensed()
- license := utils.License()
- restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelManagement
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManagement
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL })
- th.App.SetDefaultRolesBasedOnConfig()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
+
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel3 := &model.Channel{DisplayName: "Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
@@ -124,13 +113,10 @@ func TestCreateChannel(t *testing.T) {
t.Fatal(err)
}
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id, model.TEAM_ADMIN_ROLE_ID)
th.LoginBasic2()
channel2.Name = "zz" + model.NewId() + "a"
@@ -153,50 +139,6 @@ func TestCreateChannel(t *testing.T) {
if _, err := Client.CreateChannel(channel3); err != nil {
t.Fatal(err)
}
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- channel2.Name = "zz" + model.NewId() + "a"
- channel3.Name = "zz" + 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")
- }
-
- th.LinkUserToTeam(th.SystemAdminUser, team)
-
- if _, err := SystemAdminClient.CreateChannel(channel2); err != nil {
- t.Fatal(err)
- }
- if _, err := SystemAdminClient.CreateChannel(channel3); err != nil {
- t.Fatal(err)
- }
-
- // Check that if unlicensed the policy restriction is not enforced.
- utils.SetIsLicensed(false)
- utils.SetLicense(nil)
- th.App.SetDefaultRolesBasedOnConfig()
-
- channel4 := model.Channel{DisplayName: "Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
- channel5 := model.Channel{DisplayName: "Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
- if _, err := Client.CreateChannel(&channel4); err != nil {
- t.Fatal("should have succeeded")
- }
- if _, err := Client.CreateChannel(&channel5); err != nil {
- t.Fatal("should have succeeded")
- }
-
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_ALL })
- th.App.SetDefaultRolesBasedOnConfig()
}
func TestCreateDirectChannel(t *testing.T) {
@@ -367,23 +309,17 @@ func TestUpdateChannel(t *testing.T) {
t.Fatal("should have failed - channel deleted")
}
- isLicensed := utils.IsLicensed()
- license := utils.License()
- restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelManagement
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManagement
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.TEAM_USER_ROLE_ID)
+
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
channel2 := th.CreateChannel(Client, team)
channel3 := th.CreatePrivateChannel(Client, team)
@@ -402,16 +338,11 @@ func TestUpdateChannel(t *testing.T) {
t.Fatal(err)
}
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_CHANNEL_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_ADMIN_ROLE_ID)
+
th.MakeUserChannelUser(th.BasicUser, channel2)
th.MakeUserChannelUser(th.BasicUser, channel3)
sqlstore.ClearChannelCaches()
@@ -423,17 +354,6 @@ func TestUpdateChannel(t *testing.T) {
t.Fatal("should have errored not channel admin")
}
- th.UpdateUserToTeamAdmin(th.BasicUser, team)
- th.App.InvalidateAllCaches()
- if _, err := Client.UpdateChannel(channel2); err != nil {
- t.Fatal(err)
- }
- if _, err := Client.UpdateChannel(channel3); err != nil {
- t.Fatal(err)
- }
- th.UpdateUserToNonTeamAdmin(th.BasicUser, team)
- th.App.InvalidateAllCaches()
-
th.MakeUserChannelAdmin(th.BasicUser, channel2)
th.MakeUserChannelAdmin(th.BasicUser, channel3)
sqlstore.ClearChannelCaches()
@@ -444,75 +364,6 @@ func TestUpdateChannel(t *testing.T) {
if _, err := Client.UpdateChannel(channel3); err != nil {
t.Fatal(err)
}
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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")
- }
-
- th.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)
- }
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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)
- }
-
- // Check that if unlicensed the policy restriction is not enforced.
- utils.SetIsLicensed(false)
- utils.SetLicense(nil)
- th.App.SetDefaultRolesBasedOnConfig()
-
- if _, err := Client.UpdateChannel(channel2); err != nil {
- t.Fatal(err)
- }
- if _, err := Client.UpdateChannel(channel3); err != nil {
- t.Fatal(err)
- }
}
func TestUpdateChannelDisplayName(t *testing.T) {
@@ -548,7 +399,6 @@ func TestUpdateChannelHeader(t *testing.T) {
defer th.TearDown()
Client := th.BasicClient
- SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
@@ -618,23 +468,17 @@ func TestUpdateChannelHeader(t *testing.T) {
t.Fatal("should have errored non-channel member trying to update header")
}
- isLicensed := utils.IsLicensed()
- license := utils.License()
- restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelManagement
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManagement
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.TEAM_USER_ROLE_ID)
+
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
th.LoginBasic()
channel2 := th.CreateChannel(Client, team)
@@ -657,13 +501,11 @@ func TestUpdateChannelHeader(t *testing.T) {
t.Fatal(err)
}
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_ADMIN_ROLE_ID)
+
th.MakeUserChannelUser(th.BasicUser, channel2)
th.MakeUserChannelUser(th.BasicUser, channel3)
sqlstore.ClearChannelCaches()
@@ -685,72 +527,6 @@ func TestUpdateChannelHeader(t *testing.T) {
if _, err := Client.UpdateChannelHeader(data3); err != nil {
t.Fatal(err)
}
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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")
- }
-
- th.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)
- }
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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")
- }
-
- th.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)
- }
-
- // Check that if unlicensed the policy restriction is not enforced.
- utils.SetIsLicensed(false)
- utils.SetLicense(nil)
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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) {
@@ -758,7 +534,6 @@ func TestUpdateChannelPurpose(t *testing.T) {
defer th.TearDown()
Client := th.BasicClient
- SystemAdminClient := th.SystemAdminClient
team := th.BasicTeam
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
@@ -814,23 +589,17 @@ func TestUpdateChannelPurpose(t *testing.T) {
t.Fatal("should have errored non-channel member trying to update purpose")
}
- isLicensed := utils.IsLicensed()
- license := utils.License()
- restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelManagement
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManagement
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.TEAM_USER_ROLE_ID)
+
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
th.LoginBasic()
channel2 := th.CreateChannel(Client, team)
@@ -853,13 +622,11 @@ func TestUpdateChannelPurpose(t *testing.T) {
t.Fatal(err)
}
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, model.CHANNEL_ADMIN_ROLE_ID)
+
th.MakeUserChannelUser(th.BasicUser, channel2)
th.MakeUserChannelUser(th.BasicUser, channel3)
sqlstore.ClearChannelCaches()
@@ -881,71 +648,6 @@ func TestUpdateChannelPurpose(t *testing.T) {
if _, err := Client.UpdateChannelPurpose(data3); err != nil {
t.Fatal(err)
}
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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")
- }
-
- th.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)
- }
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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")
- }
-
- th.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)
- }
-
- // Check that if unlicensed the policy restriction is not enforced.
- utils.SetIsLicensed(false)
- utils.SetLicense(nil)
- th.App.SetDefaultRolesBasedOnConfig()
- if _, err := SystemAdminClient.UpdateChannelHeader(data2); err != nil {
- t.Fatal(err)
- }
- if _, err := SystemAdminClient.UpdateChannelHeader(data3); err != nil {
- t.Fatal(err)
- }
}
func TestGetChannel(t *testing.T) {
@@ -1400,23 +1102,14 @@ func TestDeleteChannel(t *testing.T) {
t.Fatal("should have failed - channel already deleted")
}
- isLicensed := utils.IsLicensed()
- license := utils.License()
- restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelManagement
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManagement
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
th.LoginSystemAdmin()
th.LinkUserToTeam(th.BasicUser, team)
@@ -1438,16 +1131,10 @@ func TestDeleteChannel(t *testing.T) {
t.Fatal(err)
}
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.CHANNEL_ADMIN_ROLE_ID)
th.LoginSystemAdmin()
@@ -1480,78 +1167,6 @@ func TestDeleteChannel(t *testing.T) {
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))
- th.UpdateUserToTeamAdmin(th.BasicUser, team)
-
- Client.Login(th.BasicUser.Email, th.BasicUser.Password)
- th.App.InvalidateAllCaches()
-
- if _, err := Client.DeleteChannel(channel2.Id); err != nil {
- t.Fatal(err)
- }
- if _, err := Client.DeleteChannel(channel3.Id); err != nil {
- t.Fatal(err)
- }
-
- th.UpdateUserToNonTeamAdmin(th.BasicUser, team)
- th.App.InvalidateAllCaches()
-
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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")
- }
-
- th.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.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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))
@@ -1576,29 +1191,6 @@ func TestDeleteChannel(t *testing.T) {
if _, err := Client.DeleteChannel(channel3.Id); err != nil {
t.Fatal(err)
}
-
- // Check that if unlicensed the policy restriction is not enforced.
- utils.SetIsLicensed(false)
- utils.SetLicense(nil)
- th.App.SetDefaultRolesBasedOnConfig()
-
- 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(err)
- }
- if _, err := Client.DeleteChannel(channel3.Id); err != nil {
- t.Fatal(err)
- }
-
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_ALL })
- th.App.SetDefaultRolesBasedOnConfig()
}
func TestGetChannelStats(t *testing.T) {
@@ -1674,38 +1266,14 @@ func TestAddChannelMember(t *testing.T) {
t.Fatal("Should have errored, user not on team")
}
- // Test policy does not apply to TE.
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManageMembers
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = restrictPrivateChannel
- })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
- channel3 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
- channel3 = Client.Must(th.SystemAdminClient.CreateChannel(channel3)).Data.(*model.Channel)
- Client.Must(th.SystemAdminClient.AddChannelMember(channel3.Id, user1.Id))
- if _, err := Client.AddChannelMember(channel3.Id, user2.Id); err != nil {
- t.Fatal(err)
- }
-
- // Add a license
- isLicensed := utils.IsLicensed()
- license := utils.License()
- defer func() {
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
- }()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
// Check that a regular channel user can add other users.
channel4 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
@@ -1715,14 +1283,10 @@ func TestAddChannelMember(t *testing.T) {
t.Fatal(err)
}
- // Test with CHANNEL_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_ADMIN_ROLE_ID)
channel5 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel5 = Client.Must(th.SystemAdminClient.CreateChannel(channel5)).Data.(*model.Channel)
@@ -1733,61 +1297,10 @@ func TestAddChannelMember(t *testing.T) {
th.MakeUserChannelAdmin(user1, channel5)
th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
if _, err := Client.AddChannelMember(channel5.Id, user2.Id); err != nil {
t.Fatal(err)
}
-
- // Test with TEAM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_TEAM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- channel6 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
- channel6 = Client.Must(th.SystemAdminClient.CreateChannel(channel6)).Data.(*model.Channel)
- Client.Must(th.SystemAdminClient.AddChannelMember(channel6.Id, user1.Id))
- if _, err := Client.AddChannelMember(channel6.Id, user2.Id); err == nil {
- t.Fatal("Should have failed due to permissions")
- }
-
- th.UpdateUserToTeamAdmin(user1, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- if _, err := Client.AddChannelMember(channel6.Id, user2.Id); err != nil {
- t.Fatal(err)
- }
-
- // Test with SYSTEM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_SYSTEM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- channel7 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
- channel7 = Client.Must(th.SystemAdminClient.CreateChannel(channel7)).Data.(*model.Channel)
- Client.Must(th.SystemAdminClient.AddChannelMember(channel7.Id, user1.Id))
- if _, err := Client.AddChannelMember(channel7.Id, user2.Id); err == nil {
- t.Fatal("Should have failed due to permissions")
- }
-
- if _, err := th.SystemAdminClient.AddChannelMember(channel7.Id, user2.Id); err != nil {
- t.Fatal(err)
- }
}
func TestRemoveChannelMember(t *testing.T) {
@@ -1859,39 +1372,14 @@ func TestRemoveChannelMember(t *testing.T) {
th.LoginBasic()
- // Test policy does not apply to TE.
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManageMembers
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = restrictPrivateChannel
- })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
- channel3 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
- channel3 = Client.Must(th.SystemAdminClient.CreateChannel(channel3)).Data.(*model.Channel)
- Client.Must(th.SystemAdminClient.AddChannelMember(channel3.Id, user1.Id))
- Client.Must(th.SystemAdminClient.AddChannelMember(channel3.Id, user2.Id))
- if _, err := Client.RemoveChannelMember(channel3.Id, user2.Id); err != nil {
- t.Fatal(err)
- }
-
- // Add a license
- isLicensed := utils.IsLicensed()
- license := utils.License()
- defer func() {
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
- }()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
// Check that a regular channel user can remove other users.
channel4 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
@@ -1902,14 +1390,10 @@ func TestRemoveChannelMember(t *testing.T) {
t.Fatal(err)
}
- // Test with CHANNEL_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_ADMIN_ROLE_ID)
channel5 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
channel5 = Client.Must(th.SystemAdminClient.CreateChannel(channel5)).Data.(*model.Channel)
@@ -1921,62 +1405,10 @@ func TestRemoveChannelMember(t *testing.T) {
th.MakeUserChannelAdmin(user1, channel5)
th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
if _, err := Client.RemoveChannelMember(channel5.Id, user2.Id); err != nil {
t.Fatal(err)
}
-
- // Test with TEAM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_TEAM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- channel6 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
- channel6 = Client.Must(th.SystemAdminClient.CreateChannel(channel6)).Data.(*model.Channel)
- Client.Must(th.SystemAdminClient.AddChannelMember(channel6.Id, user1.Id))
- Client.Must(th.SystemAdminClient.AddChannelMember(channel6.Id, user2.Id))
- if _, err := Client.RemoveChannelMember(channel6.Id, user2.Id); err == nil {
- t.Fatal("Should have failed due to permissions")
- }
-
- th.UpdateUserToTeamAdmin(user1, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- if _, err := Client.RemoveChannelMember(channel6.Id, user2.Id); err != nil {
- t.Fatal(err)
- }
-
- // Test with SYSTEM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_SYSTEM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- channel7 := &model.Channel{DisplayName: "A Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id}
- channel7 = Client.Must(th.SystemAdminClient.CreateChannel(channel7)).Data.(*model.Channel)
- Client.Must(th.SystemAdminClient.AddChannelMember(channel7.Id, user1.Id))
- Client.Must(th.SystemAdminClient.AddChannelMember(channel7.Id, user2.Id))
- if _, err := Client.RemoveChannelMember(channel7.Id, user2.Id); err == nil {
- t.Fatal("Should have failed due to permissions")
- }
-
- if _, err := th.SystemAdminClient.RemoveChannelMember(channel7.Id, user2.Id); err != nil {
- t.Fatal(err)
- }
}
func TestUpdateNotifyProps(t *testing.T) {
diff --git a/api/oauth_test.go b/api/oauth_test.go
index ec1e557da..2663c784b 100644
--- a/api/oauth_test.go
+++ b/api/oauth_test.go
@@ -88,7 +88,12 @@ func TestOAuthRegisterApp(t *testing.T) {
t.Fatal("should have failed. not enough permissions")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
th.LoginBasic()
@@ -210,7 +215,12 @@ func TestOAuthGetAppsByUser(t *testing.T) {
t.Fatal("Should have failed.")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
if result, err := Client.GetOAuthAppsByUser(); err != nil {
t.Fatal(err)
@@ -250,7 +260,9 @@ func TestOAuthGetAppsByUser(t *testing.T) {
user := &model.User{Email: strings.ToLower("test+"+model.NewId()) + "@simulator.amazonses.com", Password: "hello1", Username: "n" + model.NewId(), EmailVerified: true}
ruser := Client.Must(AdminClient.CreateUser(user, "")).Data.(*model.User)
- th.App.UpdateUserRoles(ruser.Id, "", false)
+ if _, err := th.App.UpdateUserRoles(ruser.Id, "", false); err != nil {
+ t.Fatal(err)
+ }
Client.Logout()
Client.Login(user.Email, user.Password)
@@ -437,7 +449,13 @@ func TestOAuthDeleteApp(t *testing.T) {
}
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oauthApp := &model.OAuthApp{Name: "TestApp5" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -492,13 +510,17 @@ func TestOAuthAccessToken(t *testing.T) {
Client := th.BasicClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oauthApp := &model.OAuthApp{Name: "TestApp5" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
oauthApp = Client.Must(Client.RegisterApp(oauthApp)).Data.(*model.OAuthApp)
@@ -739,7 +761,13 @@ func TestOAuthComplete(t *testing.T) {
// We are going to use mattermost as the provider emulating gitlab
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oauthApp := &model.OAuthApp{
Name: "TestApp5" + model.NewId(),
diff --git a/api/post_test.go b/api/post_test.go
index 299fdf046..fe0c2a6b7 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -167,10 +167,8 @@ func TestCreatePost(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = disableTownSquareReadOnly })
utils.SetIsLicensed(isLicensed)
utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true })
- th.App.SetDefaultRolesBasedOnConfig()
utils.SetIsLicensed(true)
utils.SetLicense(&model.License{Features: &model.Features{}})
utils.License().Features.SetDefaults()
@@ -965,9 +963,6 @@ func TestDeletePosts(t *testing.T) {
channel1 := th.BasicChannel
team1 := th.BasicTeam
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.RestrictPostDelete = model.PERMISSIONS_DELETE_POST_ALL })
- th.App.SetDefaultRolesBasedOnConfig()
-
time.Sleep(10 * time.Millisecond)
post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
@@ -1020,16 +1015,11 @@ func TestDeletePosts(t *testing.T) {
t.Fatal(err)
}
- // Test licensed policy controls for delete post
- isLicensed := utils.IsLicensed()
- license := utils.License()
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
th.UpdateUserToTeamAdmin(th.BasicUser2, th.BasicTeam)
@@ -1041,10 +1031,8 @@ func TestDeletePosts(t *testing.T) {
SystemAdminClient.Must(SystemAdminClient.DeletePost(channel1.Id, post4b.Id))
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.ServiceSettings.RestrictPostDelete = model.PERMISSIONS_DELETE_POST_TEAM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_POST.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_DELETE_POST.Id, model.TEAM_ADMIN_ROLE_ID)
th.LoginBasic()
@@ -1065,43 +1053,6 @@ func TestDeletePosts(t *testing.T) {
Client.Must(Client.DeletePost(channel1.Id, post5a.Id))
SystemAdminClient.Must(SystemAdminClient.DeletePost(channel1.Id, post5b.Id))
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.ServiceSettings.RestrictPostDelete = model.PERMISSIONS_DELETE_POST_SYSTEM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- th.LoginBasic()
-
- time.Sleep(10 * time.Millisecond)
- post6a := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"}
- post6a = Client.Must(Client.CreatePost(post6a)).Data.(*model.Post)
-
- if _, err := Client.DeletePost(channel1.Id, post6a.Id); err == nil {
- t.Fatal(err)
- }
-
- th.LoginBasic2()
-
- if _, err := Client.DeletePost(channel1.Id, post6a.Id); err == nil {
- t.Fatal(err)
- }
-
- // Check that if unlicensed the policy restriction is not enforced.
- utils.SetIsLicensed(false)
- utils.SetLicense(nil)
- th.App.SetDefaultRolesBasedOnConfig()
-
- time.Sleep(10 * time.Millisecond)
- post7 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"}
- post7 = Client.Must(Client.CreatePost(post7)).Data.(*model.Post)
-
- if _, err := Client.DeletePost(channel1.Id, post7.Id); err != nil {
- t.Fatal(err)
- }
-
- SystemAdminClient.Must(SystemAdminClient.DeletePost(channel1.Id, post6a.Id))
-
}
func TestEmailMention(t *testing.T) {
diff --git a/api/team.go b/api/team.go
index 48377f970..e89f368ec 100644
--- a/api/team.go
+++ b/api/team.go
@@ -13,7 +13,6 @@ import (
"github.com/gorilla/mux"
"github.com/mattermost/mattermost-server/model"
- "github.com/mattermost/mattermost-server/utils"
)
func (api *API) InitTeam() {
@@ -117,15 +116,8 @@ func getAll(c *Context, w http.ResponseWriter, r *http.Request) {
func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
invites := model.InvitesFromJson(r.Body)
- if utils.IsLicensed() && !c.App.SessionHasPermissionToTeam(c.Session, c.TeamId, model.PERMISSION_INVITE_USER) {
- errorId := ""
- if *c.App.Config().TeamSettings.RestrictTeamInvite == model.PERMISSIONS_SYSTEM_ADMIN {
- errorId = "api.team.invite_members.restricted_system_admin.app_error"
- } else if *c.App.Config().TeamSettings.RestrictTeamInvite == model.PERMISSIONS_TEAM_ADMIN {
- errorId = "api.team.invite_members.restricted_team_admin.app_error"
- }
-
- c.Err = model.NewAppError("inviteMembers", errorId, nil, "", http.StatusForbidden)
+ if !c.App.SessionHasPermissionToTeam(c.Session, c.TeamId, model.PERMISSION_INVITE_USER) {
+ c.SetPermissionError(model.PERMISSION_INVITE_USER)
return
}
diff --git a/api/team_test.go b/api/team_test.go
index b1c892544..3db454b62 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -139,32 +139,17 @@ func TestAddUserToTeam(t *testing.T) {
t.Fatal(err)
}
- // Restore config/license at end of test case.
- restrictTeamInvite := *th.App.Config().TeamSettings.RestrictTeamInvite
- isLicensed := utils.IsLicensed()
- license := utils.License()
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Set the config so that only team admins can add a user to a team.
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
-
- // Test without the EE license to see that the permission restriction is ignored.
- user3 := th.CreateUser(th.BasicClient)
- if _, err := th.BasicClient.AddUserToTeam(th.BasicTeam.Id, user3.Id); err != nil {
- t.Fatal(err)
- }
-
- // Add an EE license.
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.AddPermissionToRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_USER_ROLE_ID)
// Check that a regular user can't add someone to the team.
user4 := th.CreateUser(th.BasicClient)
@@ -175,32 +160,17 @@ func TestAddUserToTeam(t *testing.T) {
// Should work as team admin.
th.UpdateUserToTeamAdmin(th.BasicUser, th.BasicTeam)
th.App.InvalidateAllCaches()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Change permission level to team user
+ th.AddPermissionToRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_ADMIN_ROLE_ID)
user5 := th.CreateUser(th.BasicClient)
if _, err := th.BasicClient.AddUserToTeam(th.BasicTeam.Id, user5.Id); err != nil {
t.Fatal(err)
}
-
- // Change permission level to System Admin
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_SYSTEM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
-
- // Should not work as team admin.
- user6 := th.CreateUser(th.BasicClient)
- if _, err := th.BasicClient.AddUserToTeam(th.BasicTeam.Id, user6.Id); err == nil {
- t.Fatal("should have failed due to permissions error")
- }
-
- // Should work as system admin.
- user7 := th.CreateUser(th.BasicClient)
- if _, err := th.SystemAdminClient.AddUserToTeam(th.BasicTeam.Id, user7.Id); err != nil {
- t.Fatal(err)
- }
}
func TestRemoveUserFromTeam(t *testing.T) {
@@ -534,7 +504,6 @@ func TestInviteMembers(t *testing.T) {
defer th.TearDown()
Client := th.BasicClient
- SystemAdminClient := th.SystemAdminClient
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
@@ -565,33 +534,21 @@ func TestInviteMembers(t *testing.T) {
t.Fatal("Should have errored out on no invites to send")
}
- restrictTeamInvite := *th.App.Config().TeamSettings.RestrictTeamInvite
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Set the config so that only team admins can add a user to a team.
+ th.AddPermissionToRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_USER_ROLE_ID)
th.LoginBasic2()
th.LinkUserToTeam(th.BasicUser2, team)
- if _, err := Client.InviteMembers(invites); err != nil {
- t.Fatal(err)
- }
-
- isLicensed := utils.IsLicensed()
- license := utils.License()
- defer func() {
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
- }()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
if _, err := Client.InviteMembers(invites); err == nil {
t.Fatal("should have errored not team admin and licensed")
}
@@ -604,19 +561,6 @@ func TestInviteMembers(t *testing.T) {
if _, err := Client.InviteMembers(invites); err != nil {
t.Fatal(err)
}
-
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_SYSTEM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
-
- if _, err := Client.InviteMembers(invites); err == nil {
- t.Fatal("should have errored not system admin and licensed")
- }
-
- th.LinkUserToTeam(th.SystemAdminUser, team)
-
- if _, err := SystemAdminClient.InviteMembers(invites); err != nil {
- t.Fatal(err)
- }
}
func TestUpdateTeamDisplayName(t *testing.T) {
diff --git a/api/webhook_test.go b/api/webhook_test.go
index b5a836603..b6b754ad3 100644
--- a/api/webhook_test.go
+++ b/api/webhook_test.go
@@ -25,8 +25,16 @@ func TestCreateIncomingHook(t *testing.T) {
user2 := th.CreateUser(Client)
th.LinkUserToTeam(user2, team)
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.IncomingWebhook{ChannelId: channel1.Id}
@@ -92,8 +100,8 @@ func TestCreateIncomingHook(t *testing.T) {
t.Fatal(err)
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
if _, err := Client.CreateIncomingWebhook(hook); err != nil {
t.Fatal(err)
@@ -132,8 +140,12 @@ func TestUpdateIncomingHook(t *testing.T) {
th.UpdateUserToTeamAdmin(user3, team2)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
hook := createIncomingWebhook(channel1.Id, Client, t)
@@ -216,8 +228,9 @@ func TestUpdateIncomingHook(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
t.Run("OnlyAdminIntegrationsDisabled", func(t *testing.T) {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
t.Run("UpdateHookOfSameUser", func(t *testing.T) {
sameUserHook := &model.IncomingWebhook{ChannelId: channel1.Id, UserId: user2.Id}
@@ -239,8 +252,8 @@ func TestUpdateIncomingHook(t *testing.T) {
})
})
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
Client.Logout()
th.UpdateUserToTeamAdmin(user2, team)
@@ -323,8 +336,15 @@ func TestListIncomingHooks(t *testing.T) {
th.LinkUserToTeam(user2, team)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook1 := &model.IncomingWebhook{ChannelId: channel1.Id}
hook1 = Client.Must(Client.CreateIncomingWebhook(hook1)).Data.(*model.IncomingWebhook)
@@ -350,8 +370,8 @@ func TestListIncomingHooks(t *testing.T) {
t.Fatal("should have errored - not system/team admin")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
if _, err := Client.ListIncomingWebhooks(); err != nil {
t.Fatal(err)
@@ -375,8 +395,15 @@ func TestDeleteIncomingHook(t *testing.T) {
th.LinkUserToTeam(user2, team)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.IncomingWebhook{ChannelId: channel1.Id}
hook = Client.Must(Client.CreateIncomingWebhook(hook)).Data.(*model.IncomingWebhook)
@@ -409,8 +436,8 @@ func TestDeleteIncomingHook(t *testing.T) {
t.Fatal("should have failed - not system/team admin")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
if _, err := Client.DeleteIncomingWebhook(hook.Id); err == nil {
t.Fatal("should have failed - not creator or team admin")
@@ -446,8 +473,15 @@ func TestCreateOutgoingHook(t *testing.T) {
th.LinkUserToTeam(user3, team2)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
@@ -517,8 +551,8 @@ func TestCreateOutgoingHook(t *testing.T) {
t.Fatal("should have failed - not system/team admin")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
if _, err := Client.CreateOutgoingWebhook(hook); err != nil {
t.Fatal(err)
@@ -550,8 +584,15 @@ func TestListOutgoingHooks(t *testing.T) {
th.LinkUserToTeam(user2, team)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook1 := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook1 = Client.Must(Client.CreateOutgoingWebhook(hook1)).Data.(*model.OutgoingWebhook)
@@ -577,8 +618,8 @@ func TestListOutgoingHooks(t *testing.T) {
t.Fatal("should have failed - not system/team admin")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
if _, err := Client.ListOutgoingWebhooks(); err != nil {
t.Fatal(err)
@@ -608,8 +649,15 @@ func TestUpdateOutgoingHook(t *testing.T) {
th.LinkUserToTeam(user3, team2)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := createOutgoingWebhook(channel1.Id, []string{"http://nowhere.com"}, []string{"cats"}, Client, t)
createOutgoingWebhook(channel1.Id, []string{"http://nowhere.com"}, []string{"dogs"}, Client, t)
@@ -682,16 +730,17 @@ func TestUpdateOutgoingHook(t *testing.T) {
t.Fatal("should have failed - user does not have permissions to manage webhooks")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
+
hook2 := createOutgoingWebhook(channel1.Id, []string{"http://nowhereelse.com"}, []string{"dogs"}, Client, t)
if _, err := Client.UpdateOutgoingWebhook(hook2); err != nil {
t.Fatal("update webhook failed when admin only integrations is turned off")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
Client.Logout()
th.LinkUserToTeam(user3, team)
@@ -778,8 +827,15 @@ func TestDeleteOutgoingHook(t *testing.T) {
th.LinkUserToTeam(user2, team)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
@@ -812,8 +868,8 @@ func TestDeleteOutgoingHook(t *testing.T) {
t.Fatal("should have failed - not system/team admin")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
if _, err := Client.DeleteOutgoingWebhook(hook.Id); err == nil {
t.Fatal("should have failed - not creator or team admin")
@@ -847,8 +903,15 @@ func TestRegenOutgoingHookToken(t *testing.T) {
th.LinkUserToTeam(user3, team2)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
@@ -882,8 +945,8 @@ func TestRegenOutgoingHookToken(t *testing.T) {
t.Fatal("should have failed - not system/team admin")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook = &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
@@ -969,10 +1032,8 @@ func TestIncomingWebhooks(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = disableTownSquareReadOnly })
utils.SetIsLicensed(isLicensed)
utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true })
- th.App.SetDefaultRolesBasedOnConfig()
utils.SetIsLicensed(true)
utils.SetLicense(&model.License{Features: &model.Features{}})
utils.License().Features.SetDefaults()
diff --git a/api4/api.go b/api4/api.go
index 580bd8c58..583a6041b 100644
--- a/api4/api.go
+++ b/api4/api.go
@@ -96,6 +96,8 @@ type Routes struct {
Reactions *mux.Router // 'api/v4/reactions'
+ Roles *mux.Router // 'api/v4/roles'
+
Emojis *mux.Router // 'api/v4/emoji'
Emoji *mux.Router // 'api/v4/emoji/{emoji_id:[A-Za-z0-9]+}'
EmojiByName *mux.Router // 'api/v4/emoji/name/{emoji_name:[A-Za-z0-9_-\.]+}'
@@ -194,6 +196,8 @@ func Init(a *app.App, root *mux.Router, full bool) *API {
api.BaseRoutes.OpenGraph = api.BaseRoutes.ApiRoot.PathPrefix("/opengraph").Subrouter()
+ api.BaseRoutes.Roles = api.BaseRoutes.ApiRoot.PathPrefix("/roles").Subrouter()
+
api.InitUser()
api.InitTeam()
api.InitChannel()
@@ -219,6 +223,7 @@ func Init(a *app.App, root *mux.Router, full bool) *API {
api.InitWebrtc()
api.InitOpenGraph()
api.InitPlugin()
+ api.InitRole()
root.Handle("/api/v4/{anything:.*}", http.HandlerFunc(Handle404))
diff --git a/api4/apitestlib.go b/api4/apitestlib.go
index a7e64ae84..bdca072c5 100644
--- a/api4/apitestlib.go
+++ b/api4/apitestlib.go
@@ -118,6 +118,7 @@ func setupTestHelper(enterprise bool) *TestHelper {
Init(th.App, th.App.Srv.Router, true)
wsapi.Init(th.App, th.App.Srv.WebSocketRouter)
th.App.Srv.Store.MarkSystemRanUnitTests()
+ th.App.DoAdvancedPermissionsMigration()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
@@ -799,3 +800,114 @@ func (me *TestHelper) UpdateUserToNonTeamAdmin(user *model.User, team *model.Tea
}
utils.EnableDebugLogForTest()
}
+
+func (me *TestHelper) SaveDefaultRolePermissions() map[string][]string {
+ utils.DisableDebugLogForTest()
+
+ results := make(map[string][]string)
+
+ for _, roleName := range []string{
+ "system_user",
+ "system_admin",
+ "team_user",
+ "team_admin",
+ "channel_user",
+ "channel_admin",
+ } {
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ results[roleName] = role.Permissions
+ }
+
+ utils.EnableDebugLogForTest()
+ return results
+}
+
+func (me *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
+ utils.DisableDebugLogForTest()
+
+ for roleName, permissions := range data {
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ if strings.Join(role.Permissions, " ") == strings.Join(permissions, " ") {
+ continue
+ }
+
+ role.Permissions = permissions
+
+ _, err2 := me.App.UpdateRole(role)
+ if err2 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err2)
+ }
+ }
+
+ utils.EnableDebugLogForTest()
+}
+
+func (me *TestHelper) RemovePermissionFromRole(permission string, roleName string) {
+ utils.DisableDebugLogForTest()
+
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ var newPermissions []string
+ for _, p := range role.Permissions {
+ if p != permission {
+ newPermissions = append(newPermissions, p)
+ }
+ }
+
+ if strings.Join(role.Permissions, " ") == strings.Join(newPermissions, " ") {
+ utils.EnableDebugLogForTest()
+ return
+ }
+
+ role.Permissions = newPermissions
+
+ _, err2 := me.App.UpdateRole(role)
+ if err2 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err2)
+ }
+
+ utils.EnableDebugLogForTest()
+}
+
+func (me *TestHelper) AddPermissionToRole(permission string, roleName string) {
+ utils.DisableDebugLogForTest()
+
+ role, err1 := me.App.GetRoleByName(roleName)
+ if err1 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err1)
+ }
+
+ for _, existingPermission := range role.Permissions {
+ if existingPermission == permission {
+ utils.EnableDebugLogForTest()
+ return
+ }
+ }
+
+ role.Permissions = append(role.Permissions, permission)
+
+ _, err2 := me.App.UpdateRole(role)
+ if err2 != nil {
+ utils.EnableDebugLogForTest()
+ panic(err2)
+ }
+
+ utils.EnableDebugLogForTest()
+}
diff --git a/api4/channel.go b/api4/channel.go
index 9801c9dc0..d46c3d559 100644
--- a/api4/channel.go
+++ b/api4/channel.go
@@ -7,6 +7,7 @@ import (
"net/http"
l4g "github.com/alecthomas/log4go"
+
"github.com/mattermost/mattermost-server/model"
)
diff --git a/api4/channel_test.go b/api4/channel_test.go
index 724b0d84b..4deceb4c4 100644
--- a/api4/channel_test.go
+++ b/api4/channel_test.go
@@ -14,7 +14,6 @@ import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store/sqlstore"
- "github.com/mattermost/mattermost-server/utils"
)
func TestCreateChannel(t *testing.T) {
@@ -79,26 +78,16 @@ func TestCreateChannel(t *testing.T) {
_, resp = Client.CreateChannel(private)
CheckForbiddenStatus(t, resp)
- th.LoginBasic()
-
- // Check permissions with policy config changes
- isLicensed := utils.IsLicensed()
- license := utils.License()
- restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelCreation
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelCreation
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelCreation = restrictPublicChannel })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelCreation = restrictPrivateChannel })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+
+ th.LoginBasic()
channel.Name = GenerateTestChannelName()
_, resp = Client.CreateChannel(channel)
@@ -108,13 +97,10 @@ func TestCreateChannel(t *testing.T) {
_, resp = Client.CreateChannel(private)
CheckNoError(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
_, resp = Client.CreateChannel(channel)
CheckForbiddenStatus(t, resp)
@@ -140,51 +126,7 @@ func TestCreateChannel(t *testing.T) {
_, resp = th.SystemAdminClient.CreateChannel(private)
CheckNoError(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- th.LoginBasic()
-
- _, resp = Client.CreateChannel(channel)
- CheckForbiddenStatus(t, resp)
-
- _, resp = Client.CreateChannel(private)
- CheckForbiddenStatus(t, resp)
-
- th.LoginTeamAdmin()
-
- _, resp = Client.CreateChannel(channel)
- CheckForbiddenStatus(t, resp)
-
- _, resp = Client.CreateChannel(private)
- CheckForbiddenStatus(t, resp)
-
- channel.Name = GenerateTestChannelName()
- _, resp = th.SystemAdminClient.CreateChannel(channel)
- CheckNoError(t, resp)
-
- private.Name = GenerateTestChannelName()
- _, resp = th.SystemAdminClient.CreateChannel(private)
- CheckNoError(t, resp)
-
- // Check that if unlicensed the policy restriction is not enforced.
- utils.SetIsLicensed(false)
- utils.SetLicense(nil)
- th.App.SetDefaultRolesBasedOnConfig()
-
- channel.Name = GenerateTestChannelName()
- _, resp = Client.CreateChannel(channel)
- CheckNoError(t, resp)
-
- private.Name = GenerateTestChannelName()
- _, resp = Client.CreateChannel(private)
- CheckNoError(t, resp)
-
+ // Test posting Garbage
if r, err := Client.DoApiPost("/channels", "garbage"); err == nil {
t.Fatal("should have errored")
} else {
@@ -887,23 +829,16 @@ func TestDeleteChannel(t *testing.T) {
th.InitBasic().InitSystemAdmin()
- isLicensed := utils.IsLicensed()
- license := utils.License()
- restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelManagement
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManagement
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.CHANNEL_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.TEAM_USER_ROLE_ID)
Client = th.Client
team = th.BasicTeam
@@ -924,13 +859,11 @@ func TestDeleteChannel(t *testing.T) {
_, resp = Client.DeleteChannel(privateChannel7.Id)
CheckNoError(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Restrict permissions to Channel Admins
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.CHANNEL_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.CHANNEL_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.CHANNEL_ADMIN_ROLE_ID)
// channels created by SystemAdmin
publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
@@ -957,129 +890,9 @@ func TestDeleteChannel(t *testing.T) {
_, resp = Client.DeleteChannel(privateChannel7.Id)
CheckNoError(t, resp)
- // // channels created by SystemAdmin
- publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
- privateChannel7 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
- th.App.AddUserToChannel(user, publicChannel6)
- th.App.AddUserToChannel(user, privateChannel7)
- th.App.AddUserToChannel(user2, privateChannel7)
-
- // successful delete by team admin
- th.UpdateUserToTeamAdmin(user, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
-
- _, resp = Client.DeleteChannel(publicChannel6.Id)
- CheckNoError(t, resp)
-
- _, resp = Client.DeleteChannel(privateChannel7.Id)
- CheckNoError(t, resp)
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_TEAM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
- th.UpdateUserToNonTeamAdmin(user, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
-
- // channels created by SystemAdmin
- publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
- privateChannel7 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
- th.App.AddUserToChannel(user, publicChannel6)
- th.App.AddUserToChannel(user, privateChannel7)
- th.App.AddUserToChannel(user2, privateChannel7)
-
- // cannot delete by user
- _, resp = Client.DeleteChannel(publicChannel6.Id)
- CheckForbiddenStatus(t, resp)
-
- _, resp = Client.DeleteChannel(privateChannel7.Id)
- CheckForbiddenStatus(t, resp)
-
- // // cannot delete by channel admin
- th.MakeUserChannelAdmin(user, publicChannel6)
- th.MakeUserChannelAdmin(user, privateChannel7)
- sqlstore.ClearChannelCaches()
-
- _, resp = Client.DeleteChannel(publicChannel6.Id)
- CheckForbiddenStatus(t, resp)
-
- _, resp = Client.DeleteChannel(privateChannel7.Id)
- CheckForbiddenStatus(t, resp)
-
- // successful delete by team admin
- th.UpdateUserToTeamAdmin(th.BasicUser, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
-
- _, resp = Client.DeleteChannel(publicChannel6.Id)
- CheckNoError(t, resp)
-
- _, resp = Client.DeleteChannel(privateChannel7.Id)
- CheckNoError(t, resp)
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPublicChannelDeletion = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelDeletion = model.PERMISSIONS_SYSTEM_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- // channels created by SystemAdmin
- publicChannel6 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_OPEN)
- privateChannel7 = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
- th.App.AddUserToChannel(user, publicChannel6)
- th.App.AddUserToChannel(user, privateChannel7)
- th.App.AddUserToChannel(user2, privateChannel7)
-
- // cannot delete by user
- _, resp = Client.DeleteChannel(publicChannel6.Id)
- CheckForbiddenStatus(t, resp)
-
- _, resp = Client.DeleteChannel(privateChannel7.Id)
- CheckForbiddenStatus(t, resp)
-
- // cannot delete by channel admin
- th.MakeUserChannelAdmin(user, publicChannel6)
- th.MakeUserChannelAdmin(user, privateChannel7)
- sqlstore.ClearChannelCaches()
-
- _, resp = Client.DeleteChannel(publicChannel6.Id)
- CheckForbiddenStatus(t, resp)
-
- _, resp = Client.DeleteChannel(privateChannel7.Id)
- CheckForbiddenStatus(t, resp)
-
- // cannot delete by team admin
- th.UpdateUserToTeamAdmin(th.BasicUser, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
-
- _, resp = Client.DeleteChannel(publicChannel6.Id)
- CheckForbiddenStatus(t, resp)
-
- _, resp = Client.DeleteChannel(privateChannel7.Id)
- CheckForbiddenStatus(t, resp)
-
- // successful delete by SystemAdmin
- _, resp = th.SystemAdminClient.DeleteChannel(publicChannel6.Id)
- CheckNoError(t, resp)
-
- _, resp = th.SystemAdminClient.DeleteChannel(privateChannel7.Id)
- CheckNoError(t, resp)
+ // Make sure team admins don't have permission to delete channels.
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id, model.CHANNEL_ADMIN_ROLE_ID)
// last member of a public channel should have required permission to delete
publicChannel6 = th.CreateChannelWithClient(th.Client, model.CHANNEL_OPEN)
@@ -1822,42 +1635,13 @@ func TestAddChannelMember(t *testing.T) {
_, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user2.Id)
CheckNoError(t, resp)
- // Test policy does not apply to TE.
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManageMembers
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = restrictPrivateChannel
- })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- Client.Login(user2.Username, user2.Password)
- privateChannel = th.CreatePrivateChannel()
- _, resp = Client.AddChannelMember(privateChannel.Id, user.Id)
- CheckNoError(t, resp)
- Client.Logout()
- Client.Login(user.Username, user.Password)
- _, resp = Client.AddChannelMember(privateChannel.Id, user3.Id)
- CheckNoError(t, resp)
- Client.Logout()
-
- // Add a license
- isLicensed := utils.IsLicensed()
- license := utils.License()
- defer func() {
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
- }()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
// Check that a regular channel user can add other users.
Client.Login(user2.Username, user2.Password)
@@ -1871,14 +1655,9 @@ func TestAddChannelMember(t *testing.T) {
CheckNoError(t, resp)
Client.Logout()
- // Test with CHANNEL_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ // Restrict the permission for adding users to Channel Admins
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
Client.Login(user2.Username, user2.Password)
privateChannel = th.CreatePrivateChannel()
@@ -1893,70 +1672,11 @@ func TestAddChannelMember(t *testing.T) {
th.MakeUserChannelAdmin(user, privateChannel)
th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- Client.Login(user.Username, user.Password)
- _, resp = Client.AddChannelMember(privateChannel.Id, user3.Id)
- CheckNoError(t, resp)
- Client.Logout()
-
- // Test with TEAM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_TEAM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- Client.Login(user2.Username, user2.Password)
- privateChannel = th.CreatePrivateChannel()
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user.Id)
- CheckNoError(t, resp)
- Client.Logout()
-
- Client.Login(user.Username, user.Password)
- _, resp = Client.AddChannelMember(privateChannel.Id, user3.Id)
- CheckForbiddenStatus(t, resp)
- Client.Logout()
-
- th.UpdateUserToTeamAdmin(user, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
Client.Login(user.Username, user.Password)
_, resp = Client.AddChannelMember(privateChannel.Id, user3.Id)
CheckNoError(t, resp)
Client.Logout()
-
- // Test with SYSTEM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_SYSTEM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- Client.Login(user2.Username, user2.Password)
- privateChannel = th.CreatePrivateChannel()
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user.Id)
- CheckNoError(t, resp)
- Client.Logout()
-
- Client.Login(user.Username, user.Password)
- _, resp = Client.AddChannelMember(privateChannel.Id, user3.Id)
- CheckForbiddenStatus(t, resp)
- Client.Logout()
-
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user3.Id)
- CheckNoError(t, resp)
}
func TestRemoveChannelMember(t *testing.T) {
@@ -2018,43 +1738,16 @@ func TestRemoveChannelMember(t *testing.T) {
th.UpdateUserToNonTeamAdmin(user1, team)
th.App.InvalidateAllCaches()
- // Test policy does not apply to TE.
- restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManageMembers
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = restrictPrivateChannel
- })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- th.App.SetDefaultRolesBasedOnConfig()
-
- privateChannel := th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user1.Id)
- CheckNoError(t, resp)
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user2.Id)
- CheckNoError(t, resp)
- _, resp = Client.RemoveUserFromChannel(privateChannel.Id, user2.Id)
- CheckNoError(t, resp)
-
- // Add a license
- isLicensed := utils.IsLicensed()
- license := utils.License()
- defer func() {
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
- }()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
// Check that a regular channel user can remove other users.
- privateChannel = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
+ privateChannel := th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
_, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user1.Id)
CheckNoError(t, resp)
_, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user2.Id)
@@ -2063,14 +1756,9 @@ func TestRemoveChannelMember(t *testing.T) {
_, resp = Client.RemoveUserFromChannel(privateChannel.Id, user2.Id)
CheckNoError(t, resp)
- // Test with CHANNEL_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_CHANNEL_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
+ // Restrict the permission for adding users to Channel Admins
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, model.CHANNEL_USER_ROLE_ID)
privateChannel = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
_, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user1.Id)
@@ -2083,58 +1771,7 @@ func TestRemoveChannelMember(t *testing.T) {
th.MakeUserChannelAdmin(user1, privateChannel)
th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
-
- _, resp = Client.RemoveUserFromChannel(privateChannel.Id, user2.Id)
- CheckNoError(t, resp)
-
- // Test with TEAM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_TEAM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- privateChannel = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user1.Id)
- CheckNoError(t, resp)
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user2.Id)
- CheckNoError(t, resp)
-
- _, resp = Client.RemoveUserFromChannel(privateChannel.Id, user2.Id)
- CheckForbiddenStatus(t, resp)
-
- th.UpdateUserToTeamAdmin(user1, team)
- th.App.InvalidateAllCaches()
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
_, resp = Client.RemoveUserFromChannel(privateChannel.Id, user2.Id)
CheckNoError(t, resp)
-
- // Test with SYSTEM_ADMIN level permission.
- th.App.UpdateConfig(func(cfg *model.Config) {
- *cfg.TeamSettings.RestrictPrivateChannelManageMembers = model.PERMISSIONS_SYSTEM_ADMIN
- })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
-
- privateChannel = th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE)
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user1.Id)
- CheckNoError(t, resp)
- _, resp = th.SystemAdminClient.AddChannelMember(privateChannel.Id, user2.Id)
- CheckNoError(t, resp)
-
- _, resp = Client.RemoveUserFromChannel(privateChannel.Id, user2.Id)
- CheckForbiddenStatus(t, resp)
-
- _, resp = th.SystemAdminClient.RemoveUserFromChannel(privateChannel.Id, user2.Id)
- CheckNoError(t, resp)
}
diff --git a/api4/context.go b/api4/context.go
index b10ea7a9b..cdb9f83db 100644
--- a/api4/context.go
+++ b/api4/context.go
@@ -641,3 +641,26 @@ func (c *Context) RequireActionId() *Context {
}
return c
}
+
+func (c *Context) RequireRoleId() *Context {
+ if c.Err != nil {
+ return c
+ }
+
+ if len(c.Params.RoleId) != 26 {
+ c.SetInvalidUrlParam("role_id")
+ }
+ return c
+}
+
+func (c *Context) RequireRoleName() *Context {
+ if c.Err != nil {
+ return c
+ }
+
+ if !model.IsValidRoleName(c.Params.RoleName) {
+ c.SetInvalidUrlParam("role_name")
+ }
+
+ return c
+}
diff --git a/api4/oauth_test.go b/api4/oauth_test.go
index 8dd602456..0959442f0 100644
--- a/api4/oauth_test.go
+++ b/api4/oauth_test.go
@@ -19,13 +19,15 @@ func TestCreateOAuthApp(t *testing.T) {
AdminClient := th.SystemAdminClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}, IsTrusted: true}
@@ -41,13 +43,15 @@ func TestCreateOAuthApp(t *testing.T) {
t.Fatal("trusted did no match")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
+
_, resp = Client.CreateOAuthApp(oapp)
CheckForbiddenStatus(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
+
rapp, resp = Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
CheckCreatedStatus(t, resp)
@@ -87,13 +91,15 @@ func TestUpdateOAuthApp(t *testing.T) {
AdminClient := th.SystemAdminClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oapp := &model.OAuthApp{
Name: "oapp",
@@ -171,8 +177,9 @@ func TestUpdateOAuthApp(t *testing.T) {
th.LoginBasic()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
+
_, resp = Client.UpdateOAuthApp(oapp)
CheckForbiddenStatus(t, resp)
@@ -181,6 +188,7 @@ func TestUpdateOAuthApp(t *testing.T) {
CheckNotFoundStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
+
_, resp = AdminClient.UpdateOAuthApp(oapp)
CheckNotImplementedStatus(t, resp)
@@ -200,14 +208,15 @@ func TestGetOAuthApps(t *testing.T) {
AdminClient := th.SystemAdminClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -250,8 +259,8 @@ func TestGetOAuthApps(t *testing.T) {
t.Fatal("wrong apps returned")
}
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.GetOAuthApps(0, 1000)
CheckForbiddenStatus(t, resp)
@@ -273,14 +282,15 @@ func TestGetOAuthApp(t *testing.T) {
AdminClient := th.SystemAdminClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -319,8 +329,8 @@ func TestGetOAuthApp(t *testing.T) {
_, resp = Client.GetOAuthApp(rapp.Id)
CheckForbiddenStatus(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.GetOAuthApp(rapp2.Id)
CheckForbiddenStatus(t, resp)
@@ -348,14 +358,15 @@ func TestGetOAuthAppInfo(t *testing.T) {
AdminClient := th.SystemAdminClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -394,8 +405,8 @@ func TestGetOAuthAppInfo(t *testing.T) {
_, resp = Client.GetOAuthAppInfo(rapp.Id)
CheckNoError(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.GetOAuthAppInfo(rapp2.Id)
CheckNoError(t, resp)
@@ -423,14 +434,15 @@ func TestDeleteOAuthApp(t *testing.T) {
AdminClient := th.SystemAdminClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -464,8 +476,9 @@ func TestDeleteOAuthApp(t *testing.T) {
_, resp = Client.DeleteOAuthApp(rapp2.Id)
CheckNoError(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
+
_, resp = Client.DeleteOAuthApp(rapp.Id)
CheckForbiddenStatus(t, resp)
@@ -491,14 +504,15 @@ func TestRegenerateOAuthAppSecret(t *testing.T) {
AdminClient := th.SystemAdminClient
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ // Grant permission to regular users.
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -536,8 +550,9 @@ func TestRegenerateOAuthAppSecret(t *testing.T) {
_, resp = Client.RegenerateOAuthAppSecret(rapp2.Id)
CheckNoError(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Revoke permission from regular users.
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
+
_, resp = Client.RegenerateOAuthAppSecret(rapp.Id)
CheckForbiddenStatus(t, resp)
@@ -627,7 +642,6 @@ func TestAuthorizeOAuthApp(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
diff --git a/api4/params.go b/api4/params.go
index 30638578b..357036e80 100644
--- a/api4/params.go
+++ b/api4/params.go
@@ -44,6 +44,8 @@ type ApiParams struct {
JobId string
JobType string
ActionId string
+ RoleId string
+ RoleName string
Page int
PerPage int
LogsPerPage int
@@ -151,6 +153,14 @@ func ApiParamsFromRequest(r *http.Request) *ApiParams {
params.ActionId = val
}
+ if val, ok := props["role_id"]; ok {
+ params.RoleId = val
+ }
+
+ if val, ok := props["role_name"]; ok {
+ params.RoleName = val
+ }
+
if val, err := strconv.Atoi(r.URL.Query().Get("page")); err != nil || val < 0 {
params.Page = PAGE_DEFAULT
} else {
diff --git a/api4/post_test.go b/api4/post_test.go
index 6f770b70a..de627d8bc 100644
--- a/api4/post_test.go
+++ b/api4/post_test.go
@@ -136,14 +136,12 @@ func testCreatePostWithOutgoingHook(
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks })
- th.App.SetDefaultRolesBasedOnConfig()
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
})
}()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
})
@@ -496,14 +494,11 @@ func TestUpdatePost(t *testing.T) {
utils.SetIsLicensed(isLicensed)
utils.SetLicense(license)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowEditPost = allowEditPost })
- th.App.SetDefaultRolesBasedOnConfig()
}()
utils.SetIsLicensed(true)
utils.SetLicense(&model.License{Features: &model.Features{}})
utils.License().Features.SetDefaults()
-
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowEditPost = model.ALLOW_EDIT_POST_ALWAYS })
- th.App.SetDefaultRolesBasedOnConfig()
post := &model.Post{ChannelId: channel.Id, Message: "zz" + model.NewId() + "a"}
rpost, resp := Client.CreatePost(post)
@@ -581,14 +576,12 @@ func TestPatchPost(t *testing.T) {
utils.SetIsLicensed(isLicensed)
utils.SetLicense(license)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowEditPost = allowEditPost })
- th.App.SetDefaultRolesBasedOnConfig()
}()
utils.SetIsLicensed(true)
utils.SetLicense(&model.License{Features: &model.Features{}})
utils.License().Features.SetDefaults()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowEditPost = model.ALLOW_EDIT_POST_ALWAYS })
- th.App.SetDefaultRolesBasedOnConfig()
post := &model.Post{
ChannelId: channel.Id,
diff --git a/api4/role.go b/api4/role.go
new file mode 100644
index 000000000..a401a8034
--- /dev/null
+++ b/api4/role.go
@@ -0,0 +1,100 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "net/http"
+
+ "github.com/mattermost/mattermost-server/model"
+)
+
+func (api *API) InitRole() {
+ api.BaseRoutes.Roles.Handle("/{role_id:[A-Za-z0-9]+}", api.ApiSessionRequiredTrustRequester(getRole)).Methods("GET")
+ api.BaseRoutes.Roles.Handle("/name/{role_name:[a-z0-9_]+}", api.ApiSessionRequiredTrustRequester(getRoleByName)).Methods("GET")
+ api.BaseRoutes.Roles.Handle("/names", api.ApiSessionRequiredTrustRequester(getRolesByNames)).Methods("POST")
+ api.BaseRoutes.Roles.Handle("/{role_id:[A-Za-z0-9]+}/patch", api.ApiSessionRequired(patchRole)).Methods("PUT")
+}
+
+func getRole(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireRoleId()
+ if c.Err != nil {
+ return
+ }
+
+ if role, err := c.App.GetRole(c.Params.RoleId); err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(role.ToJson()))
+ }
+}
+
+func getRoleByName(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireRoleName()
+ if c.Err != nil {
+ return
+ }
+
+ if role, err := c.App.GetRoleByName(c.Params.RoleName); err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(role.ToJson()))
+ }
+}
+
+func getRolesByNames(c *Context, w http.ResponseWriter, r *http.Request) {
+ rolenames := model.ArrayFromJson(r.Body)
+
+ if len(rolenames) == 0 {
+ c.SetInvalidParam("rolenames")
+ return
+ }
+
+ for _, rolename := range rolenames {
+ if !model.IsValidRoleName(rolename) {
+ c.SetInvalidParam("rolename")
+ return
+ }
+ }
+
+ if roles, err := c.App.GetRolesByNames(rolenames); err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(model.RoleListToJson(roles)))
+ }
+}
+
+func patchRole(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireRoleId()
+ if c.Err != nil {
+ return
+ }
+
+ patch := model.RolePatchFromJson(r.Body)
+ if patch == nil {
+ c.SetInvalidParam("role")
+ return
+ }
+
+ oldRole, err := c.App.GetRole(c.Params.RoleId)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
+ c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
+ return
+ }
+
+ if role, err := c.App.PatchRole(oldRole, patch); err != nil {
+ c.Err = err
+ return
+ } else {
+ c.LogAudit("")
+ w.Write([]byte(role.ToJson()))
+ }
+}
diff --git a/api4/role_test.go b/api4/role_test.go
new file mode 100644
index 000000000..64b8303e2
--- /dev/null
+++ b/api4/role_test.go
@@ -0,0 +1,184 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/mattermost/mattermost-server/model"
+)
+
+func TestGetRole(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer th.TearDown()
+
+ role := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{"manage_system", "create_public_channel"},
+ SchemeManaged: true,
+ }
+
+ res1 := <-th.App.Srv.Store.Role().Save(role)
+ assert.Nil(t, res1.Err)
+ role = res1.Data.(*model.Role)
+ defer th.App.Srv.Store.Job().Delete(role.Id)
+
+ received, resp := th.Client.GetRole(role.Id)
+ CheckNoError(t, resp)
+
+ assert.Equal(t, received.Id, role.Id)
+ assert.Equal(t, received.Name, role.Name)
+ assert.Equal(t, received.DisplayName, role.DisplayName)
+ assert.Equal(t, received.Description, role.Description)
+ assert.EqualValues(t, received.Permissions, role.Permissions)
+ assert.Equal(t, received.SchemeManaged, role.SchemeManaged)
+
+ _, resp = th.SystemAdminClient.GetRole("1234")
+ CheckBadRequestStatus(t, resp)
+
+ _, resp = th.SystemAdminClient.GetRole(model.NewId())
+ CheckNotFoundStatus(t, resp)
+}
+
+func TestGetRoleByName(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer th.TearDown()
+
+ role := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{"manage_system", "create_public_channel"},
+ SchemeManaged: true,
+ }
+
+ res1 := <-th.App.Srv.Store.Role().Save(role)
+ assert.Nil(t, res1.Err)
+ role = res1.Data.(*model.Role)
+ defer th.App.Srv.Store.Job().Delete(role.Id)
+
+ received, resp := th.Client.GetRoleByName(role.Name)
+ CheckNoError(t, resp)
+
+ assert.Equal(t, received.Id, role.Id)
+ assert.Equal(t, received.Name, role.Name)
+ assert.Equal(t, received.DisplayName, role.DisplayName)
+ assert.Equal(t, received.Description, role.Description)
+ assert.EqualValues(t, received.Permissions, role.Permissions)
+ assert.Equal(t, received.SchemeManaged, role.SchemeManaged)
+
+ _, resp = th.SystemAdminClient.GetRoleByName(strings.Repeat("abcdefghij", 10))
+ CheckBadRequestStatus(t, resp)
+
+ _, resp = th.SystemAdminClient.GetRoleByName(model.NewId())
+ CheckNotFoundStatus(t, resp)
+}
+
+func TestGetRolesByNames(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer th.TearDown()
+
+ role1 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{"manage_system", "create_public_channel"},
+ SchemeManaged: true,
+ }
+ role2 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{"manage_system", "delete_private_channel"},
+ SchemeManaged: true,
+ }
+ role3 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{"manage_system", "manage_public_channel_properties"},
+ SchemeManaged: true,
+ }
+
+ res1 := <-th.App.Srv.Store.Role().Save(role1)
+ assert.Nil(t, res1.Err)
+ role1 = res1.Data.(*model.Role)
+ defer th.App.Srv.Store.Job().Delete(role1.Id)
+
+ res2 := <-th.App.Srv.Store.Role().Save(role2)
+ assert.Nil(t, res2.Err)
+ role2 = res2.Data.(*model.Role)
+ defer th.App.Srv.Store.Job().Delete(role2.Id)
+
+ res3 := <-th.App.Srv.Store.Role().Save(role3)
+ assert.Nil(t, res3.Err)
+ role3 = res3.Data.(*model.Role)
+ defer th.App.Srv.Store.Job().Delete(role3.Id)
+
+ // Check all three roles can be found.
+ received, resp := th.Client.GetRolesByNames([]string{role1.Name, role2.Name, role3.Name})
+ CheckNoError(t, resp)
+
+ assert.Contains(t, received, role1)
+ assert.Contains(t, received, role2)
+ assert.Contains(t, received, role3)
+
+ // Check a list of invalid roles.
+ // TODO: Confirm whether no error for invalid role names is intended.
+ received, resp = th.Client.GetRolesByNames([]string{model.NewId(), model.NewId()})
+ CheckNoError(t, resp)
+
+ _, resp = th.SystemAdminClient.GetRolesByNames([]string{})
+ CheckBadRequestStatus(t, resp)
+}
+
+func TestPatchRole(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer th.TearDown()
+
+ role := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{"manage_system", "create_public_channel"},
+ SchemeManaged: true,
+ }
+
+ res1 := <-th.App.Srv.Store.Role().Save(role)
+ assert.Nil(t, res1.Err)
+ role = res1.Data.(*model.Role)
+ defer th.App.Srv.Store.Job().Delete(role.Id)
+
+ patch := &model.RolePatch{
+ Permissions: &[]string{"manage_system", "delete_public_channel"},
+ }
+
+ received, resp := th.SystemAdminClient.PatchRole(role.Id, patch)
+ CheckNoError(t, resp)
+
+ assert.Equal(t, received.Id, role.Id)
+ assert.Equal(t, received.Name, role.Name)
+ assert.Equal(t, received.DisplayName, role.DisplayName)
+ assert.Equal(t, received.Description, role.Description)
+ assert.EqualValues(t, received.Permissions, []string{"manage_system", "delete_public_channel"})
+ assert.Equal(t, received.SchemeManaged, role.SchemeManaged)
+
+ // Check a no-op patch succeeds.
+ received, resp = th.SystemAdminClient.PatchRole(role.Id, patch)
+ CheckNoError(t, resp)
+
+ received, resp = th.SystemAdminClient.PatchRole("junk", patch)
+ CheckBadRequestStatus(t, resp)
+
+ received, resp = th.Client.PatchRole(model.NewId(), patch)
+ CheckNotFoundStatus(t, resp)
+
+ received, resp = th.Client.PatchRole(role.Id, patch)
+ CheckForbiddenStatus(t, resp)
+}
diff --git a/api4/team_test.go b/api4/team_test.go
index a8696a30b..272b7372e 100644
--- a/api4/team_test.go
+++ b/api4/team_test.go
@@ -67,14 +67,14 @@ func TestCreateTeam(t *testing.T) {
_, resp = Client.CreateTeam(rteam)
CheckUnauthorizedStatus(t, resp)
- // Update permission
- enableTeamCreation := th.App.Config().TeamSettings.EnableTeamCreation
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableTeamCreation = enableTeamCreation })
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableTeamCreation = false })
- th.App.SetDefaultRolesBasedOnConfig()
+
+ th.RemovePermissionFromRole(model.PERMISSION_CREATE_TEAM.Id, model.SYSTEM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_CREATE_TEAM.Id, model.SYSTEM_ADMIN_ROLE_ID)
th.LoginBasic()
_, resp = Client.CreateTeam(team)
@@ -1292,31 +1292,18 @@ func TestAddTeamMember(t *testing.T) {
Client.Logout()
- // Check effects of config and license changes.
- restrictTeamInvite := *th.App.Config().TeamSettings.RestrictTeamInvite
- isLicensed := utils.IsLicensed()
- license := utils.License()
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Set the config so that only team admins can add a user to a team.
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
- th.LoginBasic()
-
- // Test without the EE license to see that the permission restriction is ignored.
- _, resp = Client.AddTeamMember(team.Id, otherUser.Id)
- CheckNoError(t, resp)
+ th.AddPermissionToRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_USER_ROLE_ID)
- // Add an EE license.
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
// Check that a regular user can't add someone to the team.
@@ -1326,50 +1313,26 @@ func TestAddTeamMember(t *testing.T) {
// Update user to team admin
th.UpdateUserToTeamAdmin(th.BasicUser, th.BasicTeam)
th.App.InvalidateAllCaches()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
// Should work as a team admin.
_, resp = Client.AddTeamMember(team.Id, otherUser.Id)
CheckNoError(t, resp)
- // Change permission level to System Admin
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_SYSTEM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
+ // Change permission level to team user
+ th.AddPermissionToRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_ADMIN_ROLE_ID)
- // Should not work as team admin.
- _, resp = Client.AddTeamMember(team.Id, otherUser.Id)
- CheckForbiddenStatus(t, resp)
-
- // Should work as system admin.
- _, resp = th.SystemAdminClient.AddTeamMember(team.Id, otherUser.Id)
- CheckNoError(t, resp)
-
- // Change permission level to All
th.UpdateUserToNonTeamAdmin(th.BasicUser, th.BasicTeam)
th.App.InvalidateAllCaches()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
// Should work as a regular user.
_, resp = Client.AddTeamMember(team.Id, otherUser.Id)
CheckNoError(t, resp)
- // Reset config and license.
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
- th.LoginBasic()
-
// by hash and data
Client.Login(otherUser.Email, otherUser.Password)
@@ -1506,31 +1469,18 @@ func TestAddTeamMembers(t *testing.T) {
Client.Logout()
- // Check effects of config and license changes.
- restrictTeamInvite := *th.App.Config().TeamSettings.RestrictTeamInvite
- isLicensed := utils.IsLicensed()
- license := utils.License()
+ // Check the appropriate permissions are enforced.
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite })
- utils.SetIsLicensed(isLicensed)
- utils.SetLicense(license)
- th.App.SetDefaultRolesBasedOnConfig()
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Set the config so that only team admins can add a user to a team.
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
- th.LoginBasic()
-
- // Test without the EE license to see that the permission restriction is ignored.
- _, resp = Client.AddTeamMembers(team.Id, userList)
- CheckNoError(t, resp)
+ th.AddPermissionToRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_USER_ROLE_ID)
- // Add an EE license.
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
// Check that a regular user can't add someone to the team.
@@ -1540,37 +1490,20 @@ func TestAddTeamMembers(t *testing.T) {
// Update user to team admin
th.UpdateUserToTeamAdmin(th.BasicUser, th.BasicTeam)
th.App.InvalidateAllCaches()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
// Should work as a team admin.
_, resp = Client.AddTeamMembers(team.Id, userList)
CheckNoError(t, resp)
- // Change permission level to System Admin
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_SYSTEM_ADMIN })
- th.App.SetDefaultRolesBasedOnConfig()
-
- // Should not work as team admin.
- _, resp = Client.AddTeamMembers(team.Id, userList)
- CheckForbiddenStatus(t, resp)
-
- // Should work as system admin.
- _, resp = th.SystemAdminClient.AddTeamMembers(team.Id, userList)
- CheckNoError(t, resp)
+ // Change permission level to team user
+ th.AddPermissionToRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_USER_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_INVITE_USER.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_ADD_USER_TO_TEAM.Id, model.TEAM_ADMIN_ROLE_ID)
- // Change permission level to All
th.UpdateUserToNonTeamAdmin(th.BasicUser, th.BasicTeam)
th.App.InvalidateAllCaches()
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_ALL })
- utils.SetIsLicensed(true)
- utils.SetLicense(&model.License{Features: &model.Features{}})
- utils.License().Features.SetDefaults()
- th.App.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
// Should work as a regular user.
diff --git a/api4/webhook_test.go b/api4/webhook_test.go
index 724fd0ea4..0a295b4b2 100644
--- a/api4/webhook_test.go
+++ b/api4/webhook_test.go
@@ -19,10 +19,16 @@ func TestCreateIncomingWebhook(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnablePostUsernameOverride = true })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnablePostIconOverride = true })
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
+
hook := &model.IncomingWebhook{ChannelId: th.BasicChannel.Id}
rhook, resp := th.SystemAdminClient.CreateIncomingWebhook(hook)
@@ -53,7 +59,7 @@ func TestCreateIncomingWebhook(t *testing.T) {
_, resp = Client.CreateIncomingWebhook(hook)
CheckForbiddenStatus(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
_, resp = Client.CreateIncomingWebhook(hook)
CheckNoError(t, resp)
@@ -75,7 +81,13 @@ func TestGetIncomingWebhooks(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.IncomingWebhook{ChannelId: th.BasicChannel.Id}
rhook, resp := th.SystemAdminClient.CreateIncomingWebhook(hook)
@@ -126,7 +138,7 @@ func TestGetIncomingWebhooks(t *testing.T) {
_, resp = Client.GetIncomingWebhooks(0, 1000, "")
CheckForbiddenStatus(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
_, resp = Client.GetIncomingWebhooksForTeam(th.BasicTeam.Id, 0, 1000, "")
CheckNoError(t, resp)
@@ -148,7 +160,6 @@ func TestGetIncomingWebhook(t *testing.T) {
Client := th.SystemAdminClient
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
var resp *model.Response
var rhook *model.IncomingWebhook
@@ -188,7 +199,6 @@ func TestDeleteIncomingWebhook(t *testing.T) {
Client := th.SystemAdminClient
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
var resp *model.Response
var rhook *model.IncomingWebhook
@@ -240,7 +250,13 @@ func TestCreateOutgoingWebhook(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId, CallbackURLs: []string{"http://nowhere.com"}}
@@ -268,7 +284,7 @@ func TestCreateOutgoingWebhook(t *testing.T) {
_, resp = Client.CreateOutgoingWebhook(hook)
CheckForbiddenStatus(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
_, resp = Client.CreateOutgoingWebhook(hook)
CheckNoError(t, resp)
@@ -284,7 +300,12 @@ func TestGetOutgoingWebhooks(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId, CallbackURLs: []string{"http://nowhere.com"}}
rhook, resp := th.SystemAdminClient.CreateOutgoingWebhook(hook)
@@ -352,7 +373,7 @@ func TestGetOutgoingWebhooks(t *testing.T) {
_, resp = Client.GetOutgoingWebhooks(0, 1000, "")
CheckForbiddenStatus(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
_, resp = Client.GetOutgoingWebhooksForTeam(th.BasicTeam.Id, 0, 1000, "")
CheckNoError(t, resp)
@@ -380,7 +401,6 @@ func TestGetOutgoingWebhook(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
hook := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId, CallbackURLs: []string{"http://nowhere.com"}}
@@ -411,7 +431,13 @@ func TestUpdateIncomingHook(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook1 := &model.IncomingWebhook{ChannelId: th.BasicChannel.Id}
@@ -547,10 +573,11 @@ func TestUpdateIncomingHook(t *testing.T) {
CheckForbiddenStatus(t, resp)
})
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
t.Run("OnlyAdminIntegrationsDisabled", func(t *testing.T) {
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
t.Run("UpdateHookOfSameUser", func(t *testing.T) {
sameUserHook := &model.IncomingWebhook{ChannelId: th.BasicChannel.Id, UserId: th.BasicUser2.Id}
@@ -568,7 +595,8 @@ func TestUpdateIncomingHook(t *testing.T) {
})
})
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
Client.Logout()
th.UpdateUserToTeamAdmin(th.BasicUser2, th.BasicTeam)
@@ -623,7 +651,6 @@ func TestRegenOutgoingHookToken(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
hook := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId, CallbackURLs: []string{"http://nowhere.com"}}
rhook, resp := th.SystemAdminClient.CreateOutgoingWebhook(hook)
@@ -656,7 +683,12 @@ func TestUpdateOutgoingHook(t *testing.T) {
Client := th.Client
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+ defaultRolePermissions := th.SaveDefaultRolePermissions()
+ defer func() {
+ th.RestoreDefaultRolePermissions(defaultRolePermissions)
+ }()
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
createdHook := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId,
CallbackURLs: []string{"http://nowhere.com"}, TriggerWords: []string{"cats"}}
@@ -729,7 +761,7 @@ func TestUpdateOutgoingHook(t *testing.T) {
CheckForbiddenStatus(t, resp)
})
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
hook2 := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId,
CallbackURLs: []string{"http://nowhere.com"}, TriggerWords: []string{"rats2"}}
@@ -739,7 +771,8 @@ func TestUpdateOutgoingHook(t *testing.T) {
_, resp = Client.UpdateOutgoingWebhook(createdHook2)
CheckForbiddenStatus(t, resp)
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
+ th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
+ th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
Client.Logout()
th.UpdateUserToTeamAdmin(th.BasicUser2, th.BasicTeam)
@@ -813,7 +846,6 @@ func TestDeleteOutgoingHook(t *testing.T) {
Client := th.SystemAdminClient
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableIncomingWebhooks = true })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
var resp *model.Response
var rhook *model.OutgoingWebhook
diff --git a/app/app.go b/app/app.go
index 1e46d29d0..4cc9ff7df 100644
--- a/app/app.go
+++ b/app/app.go
@@ -7,6 +7,7 @@ import (
"html/template"
"net"
"net/http"
+ "reflect"
"strings"
"sync"
"sync/atomic"
@@ -25,6 +26,8 @@ import (
"github.com/mattermost/mattermost-server/utils"
)
+const ADVANCED_PERMISSIONS_MIGRATION_KEY = "AdvancedPermissionsMigrationComplete"
+
type App struct {
goroutineCount int32
goroutineExitSignal chan struct{}
@@ -62,7 +65,6 @@ type App struct {
htmlTemplateWatcher *utils.HTMLTemplateWatcher
sessionCache *utils.Cache
- roles map[string]*model.Role
configListenerId string
licenseListenerId string
disableConfigWatch bool
@@ -120,7 +122,6 @@ func New(options ...Option) (*App, error) {
})
app.licenseListenerId = utils.AddLicenseListener(app.configOrLicenseListener)
app.regenerateClientConfig()
- app.SetDefaultRolesBasedOnConfig()
l4g.Info(utils.T("api.server.new_server.init.info"))
@@ -157,7 +158,6 @@ func New(options ...Option) (*App, error) {
func (a *App) configOrLicenseListener() {
a.regenerateClientConfig()
- a.SetDefaultRolesBasedOnConfig()
}
func (a *App) Shutdown() {
@@ -450,3 +450,57 @@ func (a *App) Handle404(w http.ResponseWriter, r *http.Request) {
utils.RenderWebError(err, w, r)
}
+
+// This function migrates the default built in roles from code/config to the database.
+func (a *App) DoAdvancedPermissionsMigration() {
+ // If the migration is already marked as completed, don't do it again.
+ if result := <-a.Srv.Store.System().GetByName(ADVANCED_PERMISSIONS_MIGRATION_KEY); result.Err == nil {
+ return
+ }
+
+ l4g.Info("Migrating roles to database.")
+ roles := model.MakeDefaultRoles()
+ roles = utils.SetRolePermissionsFromConfig(roles, a.Config())
+
+ allSucceeded := true
+
+ for _, role := range roles {
+ if result := <-a.Srv.Store.Role().Save(role); result.Err != nil {
+ // If this failed for reasons other than the role already existing, don't mark the migration as done.
+ if result2 := <-a.Srv.Store.Role().GetByName(role.Name); result2.Err != nil {
+ l4g.Critical("Failed to migrate role to database.")
+ l4g.Critical(result.Err)
+ allSucceeded = false
+ } else {
+ // If the role already existed, check it is the same and update if not.
+ fetchedRole := result.Data.(*model.Role)
+ if !reflect.DeepEqual(fetchedRole.Permissions, role.Permissions) ||
+ fetchedRole.DisplayName != role.DisplayName ||
+ fetchedRole.Description != role.Description ||
+ fetchedRole.SchemeManaged != role.SchemeManaged {
+ role.Id = fetchedRole.Id
+ if result := <-a.Srv.Store.Role().Save(role); result.Err != nil {
+ // Role is not the same, but failed to update.
+ l4g.Critical("Failed to migrate role to database.")
+ l4g.Critical(result.Err)
+ allSucceeded = false
+ }
+ }
+ }
+ }
+ }
+
+ if !allSucceeded {
+ return
+ }
+
+ system := model.System{
+ Name: ADVANCED_PERMISSIONS_MIGRATION_KEY,
+ Value: "true",
+ }
+
+ if result := <-a.Srv.Store.System().Save(&system); result.Err != nil {
+ l4g.Critical("Failed to mark advanced permissions migration as completed.")
+ l4g.Critical(result.Err)
+ }
+}
diff --git a/app/app_test.go b/app/app_test.go
index 25b19ead8..6d62bf249 100644
--- a/app/app_test.go
+++ b/app/app_test.go
@@ -9,7 +9,6 @@ import (
"testing"
l4g "github.com/alecthomas/log4go"
-
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -71,3 +70,342 @@ func TestUpdateConfig(t *testing.T) {
*cfg.ServiceSettings.SiteURL = "foo"
})
}
+
+func TestDoAdvancedPermissionsMigration(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ if testStoreSqlSupplier == nil {
+ t.Skip("This test requires a TestStore to be run.")
+ }
+
+ th.ResetRoleMigration()
+
+ th.App.DoAdvancedPermissionsMigration()
+
+ roleNames := []string{
+ "system_user",
+ "system_admin",
+ "team_user",
+ "team_admin",
+ "channel_user",
+ "channel_admin",
+ "system_post_all",
+ "system_post_all_public",
+ "system_user_access_token",
+ "team_post_all",
+ "team_post_all_public",
+ }
+
+ roles1, err1 := th.App.GetRolesByNames(roleNames)
+ assert.Nil(t, err1)
+ assert.Equal(t, len(roles1), len(roleNames))
+
+ expected1 := map[string][]string{
+ "channel_user": []string{
+ model.PERMISSION_READ_CHANNEL.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_UPLOAD_FILE.Id,
+ model.PERMISSION_GET_PUBLIC_LINK.Id,
+ model.PERMISSION_CREATE_POST.Id,
+ model.PERMISSION_EDIT_POST.Id,
+ model.PERMISSION_USE_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_DELETE_POST.Id,
+ },
+ "channel_admin": []string{
+ model.PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ },
+ "team_user": []string{
+ model.PERMISSION_LIST_TEAM_CHANNELS.Id,
+ model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
+ model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_VIEW_TEAM.Id,
+ model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_INVITE_USER.Id,
+ model.PERMISSION_ADD_USER_TO_TEAM.Id,
+ },
+ "team_post_all": []string{
+ model.PERMISSION_CREATE_POST.Id,
+ },
+ "team_post_all_public": []string{
+ model.PERMISSION_CREATE_POST_PUBLIC.Id,
+ },
+ "team_admin": []string{
+ model.PERMISSION_EDIT_OTHERS_POSTS.Id,
+ model.PERMISSION_REMOVE_USER_FROM_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM.Id,
+ model.PERMISSION_IMPORT_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM_ROLES.Id,
+ model.PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ model.PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
+ model.PERMISSION_MANAGE_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_WEBHOOKS.Id,
+ model.PERMISSION_DELETE_POST.Id,
+ model.PERMISSION_DELETE_OTHERS_POSTS.Id,
+ },
+ "system_user": []string{
+ model.PERMISSION_CREATE_DIRECT_CHANNEL.Id,
+ model.PERMISSION_CREATE_GROUP_CHANNEL.Id,
+ model.PERMISSION_PERMANENT_DELETE_USER.Id,
+ model.PERMISSION_CREATE_TEAM.Id,
+ },
+ "system_post_all": []string{
+ model.PERMISSION_CREATE_POST.Id,
+ },
+ "system_post_all_public": []string{
+ model.PERMISSION_CREATE_POST_PUBLIC.Id,
+ },
+ "system_user_access_token": []string{
+ model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_READ_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
+ },
+ "system_admin": []string{
+ model.PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE.Id,
+ model.PERMISSION_MANAGE_SYSTEM.Id,
+ model.PERMISSION_MANAGE_ROLES.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH.Id,
+ model.PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
+ model.PERMISSION_EDIT_OTHER_USERS.Id,
+ model.PERMISSION_MANAGE_OAUTH.Id,
+ model.PERMISSION_INVITE_USER.Id,
+ model.PERMISSION_DELETE_POST.Id,
+ model.PERMISSION_DELETE_OTHERS_POSTS.Id,
+ model.PERMISSION_CREATE_TEAM.Id,
+ model.PERMISSION_ADD_USER_TO_TEAM.Id,
+ model.PERMISSION_LIST_USERS_WITHOUT_TEAM.Id,
+ model.PERMISSION_MANAGE_JOBS.Id,
+ model.PERMISSION_CREATE_POST_PUBLIC.Id,
+ model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_READ_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_LIST_TEAM_CHANNELS.Id,
+ model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
+ model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_VIEW_TEAM.Id,
+ model.PERMISSION_READ_CHANNEL.Id,
+ model.PERMISSION_UPLOAD_FILE.Id,
+ model.PERMISSION_GET_PUBLIC_LINK.Id,
+ model.PERMISSION_CREATE_POST.Id,
+ model.PERMISSION_EDIT_POST.Id,
+ model.PERMISSION_USE_SLASH_COMMANDS.Id,
+ model.PERMISSION_EDIT_OTHERS_POSTS.Id,
+ model.PERMISSION_REMOVE_USER_FROM_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM.Id,
+ model.PERMISSION_IMPORT_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM_ROLES.Id,
+ model.PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ model.PERMISSION_MANAGE_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_WEBHOOKS.Id,
+ },
+ }
+
+ // Check the migration matches what's expected.
+ for name, permissions := range expected1 {
+ role, err := th.App.GetRoleByName(name)
+ assert.Nil(t, err)
+ assert.Equal(t, role.Permissions, permissions)
+ }
+
+ // Add a license and change the policy config.
+ isLicensed := utils.IsLicensed()
+ license := utils.License()
+ restrictPublicChannel := *th.App.Config().TeamSettings.RestrictPublicChannelManagement
+ restrictPrivateChannel := *th.App.Config().TeamSettings.RestrictPrivateChannelManagement
+
+ defer func() {
+ th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel })
+ th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel })
+ utils.SetIsLicensed(isLicensed)
+ utils.SetLicense(license)
+ }()
+
+ th.App.UpdateConfig(func(cfg *model.Config) {
+ *cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ })
+ th.App.UpdateConfig(func(cfg *model.Config) {
+ *cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ })
+ utils.SetIsLicensed(true)
+ utils.SetLicense(&model.License{Features: &model.Features{}})
+ utils.License().Features.SetDefaults()
+
+ // Check the migration doesn't change anything if run again.
+ th.App.DoAdvancedPermissionsMigration()
+
+ roles2, err2 := th.App.GetRolesByNames(roleNames)
+ assert.Nil(t, err2)
+ assert.Equal(t, len(roles2), len(roleNames))
+
+ for name, permissions := range expected1 {
+ role, err := th.App.GetRoleByName(name)
+ assert.Nil(t, err)
+ assert.Equal(t, permissions, role.Permissions)
+ }
+
+ // Reset the database
+ th.ResetRoleMigration()
+
+ // Do the migration again with different policy config settings and a license.
+ th.App.DoAdvancedPermissionsMigration()
+
+ // Check the role permissions.
+ expected2 := map[string][]string{
+ "channel_user": []string{
+ model.PERMISSION_READ_CHANNEL.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_UPLOAD_FILE.Id,
+ model.PERMISSION_GET_PUBLIC_LINK.Id,
+ model.PERMISSION_CREATE_POST.Id,
+ model.PERMISSION_EDIT_POST.Id,
+ model.PERMISSION_USE_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_DELETE_POST.Id,
+ },
+ "channel_admin": []string{
+ model.PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ },
+ "team_user": []string{
+ model.PERMISSION_LIST_TEAM_CHANNELS.Id,
+ model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
+ model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_VIEW_TEAM.Id,
+ model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_INVITE_USER.Id,
+ model.PERMISSION_ADD_USER_TO_TEAM.Id,
+ },
+ "team_post_all": []string{
+ model.PERMISSION_CREATE_POST.Id,
+ },
+ "team_post_all_public": []string{
+ model.PERMISSION_CREATE_POST_PUBLIC.Id,
+ },
+ "team_admin": []string{
+ model.PERMISSION_EDIT_OTHERS_POSTS.Id,
+ model.PERMISSION_REMOVE_USER_FROM_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM.Id,
+ model.PERMISSION_IMPORT_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM_ROLES.Id,
+ model.PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ model.PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
+ model.PERMISSION_MANAGE_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_WEBHOOKS.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_DELETE_POST.Id,
+ model.PERMISSION_DELETE_OTHERS_POSTS.Id,
+ },
+ "system_user": []string{
+ model.PERMISSION_CREATE_DIRECT_CHANNEL.Id,
+ model.PERMISSION_CREATE_GROUP_CHANNEL.Id,
+ model.PERMISSION_PERMANENT_DELETE_USER.Id,
+ model.PERMISSION_CREATE_TEAM.Id,
+ },
+ "system_post_all": []string{
+ model.PERMISSION_CREATE_POST.Id,
+ },
+ "system_post_all_public": []string{
+ model.PERMISSION_CREATE_POST_PUBLIC.Id,
+ },
+ "system_user_access_token": []string{
+ model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_READ_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
+ },
+ "system_admin": []string{
+ model.PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE.Id,
+ model.PERMISSION_MANAGE_SYSTEM.Id,
+ model.PERMISSION_MANAGE_ROLES.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
+ model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH.Id,
+ model.PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
+ model.PERMISSION_EDIT_OTHER_USERS.Id,
+ model.PERMISSION_MANAGE_OAUTH.Id,
+ model.PERMISSION_INVITE_USER.Id,
+ model.PERMISSION_DELETE_POST.Id,
+ model.PERMISSION_DELETE_OTHERS_POSTS.Id,
+ model.PERMISSION_CREATE_TEAM.Id,
+ model.PERMISSION_ADD_USER_TO_TEAM.Id,
+ model.PERMISSION_LIST_USERS_WITHOUT_TEAM.Id,
+ model.PERMISSION_MANAGE_JOBS.Id,
+ model.PERMISSION_CREATE_POST_PUBLIC.Id,
+ model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_READ_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
+ model.PERMISSION_LIST_TEAM_CHANNELS.Id,
+ model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
+ model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_VIEW_TEAM.Id,
+ model.PERMISSION_READ_CHANNEL.Id,
+ model.PERMISSION_UPLOAD_FILE.Id,
+ model.PERMISSION_GET_PUBLIC_LINK.Id,
+ model.PERMISSION_CREATE_POST.Id,
+ model.PERMISSION_EDIT_POST.Id,
+ model.PERMISSION_USE_SLASH_COMMANDS.Id,
+ model.PERMISSION_EDIT_OTHERS_POSTS.Id,
+ model.PERMISSION_REMOVE_USER_FROM_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM.Id,
+ model.PERMISSION_IMPORT_TEAM.Id,
+ model.PERMISSION_MANAGE_TEAM_ROLES.Id,
+ model.PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ model.PERMISSION_MANAGE_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
+ model.PERMISSION_MANAGE_WEBHOOKS.Id,
+ },
+ }
+
+ roles3, err3 := th.App.GetRolesByNames(roleNames)
+ assert.Nil(t, err3)
+ assert.Equal(t, len(roles3), len(roleNames))
+
+ for name, permissions := range expected2 {
+ role, err := th.App.GetRoleByName(name)
+ assert.Nil(t, err)
+ assert.Equal(t, permissions, role.Permissions)
+ }
+
+ // Remove the license.
+ utils.SetIsLicensed(false)
+
+ // Do the migration again.
+ th.ResetRoleMigration()
+ th.App.DoAdvancedPermissionsMigration()
+
+ // Check the role permissions.
+ roles4, err4 := th.App.GetRolesByNames(roleNames)
+ assert.Nil(t, err4)
+ assert.Equal(t, len(roles4), len(roleNames))
+
+ for name, permissions := range expected1 {
+ role, err := th.App.GetRoleByName(name)
+ assert.Nil(t, err)
+ assert.Equal(t, permissions, role.Permissions)
+ }
+}
diff --git a/app/apptestlib.go b/app/apptestlib.go
index 09afc8f76..2b56c7ded 100644
--- a/app/apptestlib.go
+++ b/app/apptestlib.go
@@ -13,6 +13,7 @@ import (
l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/mattermost-server/einterfaces"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/plugin/pluginenv"
@@ -43,12 +44,16 @@ func (*persistentTestStore) Close() {}
var testStoreContainer *storetest.RunningContainer
var testStore *persistentTestStore
+var testStoreSqlSupplier *sqlstore.SqlSupplier
+var testClusterInterface *FakeClusterInterface
// UseTestStore sets the container and corresponding settings to use for tests. Once the tests are
// complete (e.g. at the end of your TestMain implementation), you should call StopTestStore.
func UseTestStore(container *storetest.RunningContainer, settings *model.SqlSettings) {
+ testClusterInterface = &FakeClusterInterface{}
testStoreContainer = container
- testStore = &persistentTestStore{store.NewLayeredStore(sqlstore.NewSqlSupplier(*settings, nil), nil, nil)}
+ testStoreSqlSupplier = sqlstore.NewSqlSupplier(*settings, nil)
+ testStore = &persistentTestStore{store.NewLayeredStore(testStoreSqlSupplier, nil, testClusterInterface)}
}
func StopTestStore() {
@@ -98,6 +103,9 @@ func setupTestHelper(enterprise bool) *TestHelper {
}
th.App.StartServer()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress })
+
+ th.App.DoAdvancedPermissionsMigration()
+
th.App.Srv.Store.MarkSystemRanUnitTests()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
@@ -313,3 +321,45 @@ func (me *TestHelper) InstallPlugin(manifest *model.Manifest, hooks plugin.Hooks
panic(err)
}
}
+
+func (me *TestHelper) ResetRoleMigration() {
+ if _, err := testStoreSqlSupplier.GetMaster().Exec("DELETE from Roles"); err != nil {
+ panic(err)
+ }
+
+ testClusterInterface.sendClearRoleCacheMessage()
+
+ if _, err := testStoreSqlSupplier.GetMaster().Exec("DELETE from Systems where Name = :Name", map[string]interface{}{"Name": ADVANCED_PERMISSIONS_MIGRATION_KEY}); err != nil {
+ panic(err)
+ }
+}
+
+type FakeClusterInterface struct {
+ clusterMessageHandler einterfaces.ClusterMessageHandler
+}
+
+func (me *FakeClusterInterface) StartInterNodeCommunication() {}
+func (me *FakeClusterInterface) StopInterNodeCommunication() {}
+func (me *FakeClusterInterface) RegisterClusterMessageHandler(event string, crm einterfaces.ClusterMessageHandler) {
+ me.clusterMessageHandler = crm
+}
+func (me *FakeClusterInterface) GetClusterId() string { return "" }
+func (me *FakeClusterInterface) IsLeader() bool { return false }
+func (me *FakeClusterInterface) GetMyClusterInfo() *model.ClusterInfo { return nil }
+func (me *FakeClusterInterface) GetClusterInfos() []*model.ClusterInfo { return nil }
+func (me *FakeClusterInterface) SendClusterMessage(cluster *model.ClusterMessage) {}
+func (me *FakeClusterInterface) NotifyMsg(buf []byte) {}
+func (me *FakeClusterInterface) GetClusterStats() ([]*model.ClusterStats, *model.AppError) {
+ return nil, nil
+}
+func (me *FakeClusterInterface) GetLogs(page, perPage int) ([]string, *model.AppError) {
+ return []string{}, nil
+}
+func (me *FakeClusterInterface) ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError {
+ return nil
+}
+func (me *FakeClusterInterface) sendClearRoleCacheMessage() {
+ me.clusterMessageHandler(&model.ClusterMessage{
+ Event: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES,
+ })
+}
diff --git a/app/authorization.go b/app/authorization.go
index 3a64bb717..632dd7566 100644
--- a/app/authorization.go
+++ b/app/authorization.go
@@ -12,7 +12,7 @@ import (
)
func (a *App) SessionHasPermissionTo(session model.Session, permission *model.Permission) bool {
- if !a.CheckIfRolesGrantPermission(session.GetUserRoles(), permission.Id) {
+ if !a.RolesGrantPermission(session.GetUserRoles(), permission.Id) {
a.ClearSessionCacheForUser(session.UserId)
return false
}
@@ -28,12 +28,12 @@ func (a *App) SessionHasPermissionToTeam(session model.Session, teamId string, p
teamMember := session.GetTeamByTeamId(teamId)
if teamMember != nil {
- if a.CheckIfRolesGrantPermission(teamMember.GetRoles(), permission.Id) {
+ if a.RolesGrantPermission(teamMember.GetRoles(), permission.Id) {
return true
}
}
- return a.CheckIfRolesGrantPermission(session.GetUserRoles(), permission.Id)
+ return a.RolesGrantPermission(session.GetUserRoles(), permission.Id)
}
func (a *App) SessionHasPermissionToChannel(session model.Session, channelId string, permission *model.Permission) bool {
@@ -48,7 +48,7 @@ func (a *App) SessionHasPermissionToChannel(session model.Session, channelId str
ids := cmcresult.Data.(map[string]string)
if roles, ok := ids[channelId]; ok {
channelRoles = strings.Fields(roles)
- if a.CheckIfRolesGrantPermission(channelRoles, permission.Id) {
+ if a.RolesGrantPermission(channelRoles, permission.Id) {
return true
}
}
@@ -69,7 +69,7 @@ func (a *App) SessionHasPermissionToChannelByPost(session model.Session, postId
if result := <-a.Srv.Store.Channel().GetMemberForPost(postId, session.UserId); result.Err == nil {
channelMember = result.Data.(*model.ChannelMember)
- if a.CheckIfRolesGrantPermission(channelMember.GetRoles(), permission.Id) {
+ if a.RolesGrantPermission(channelMember.GetRoles(), permission.Id) {
return true
}
}
@@ -119,7 +119,7 @@ func (a *App) HasPermissionTo(askingUserId string, permission *model.Permission)
roles := user.GetRoles()
- return a.CheckIfRolesGrantPermission(roles, permission.Id)
+ return a.RolesGrantPermission(roles, permission.Id)
}
func (a *App) HasPermissionToTeam(askingUserId string, teamId string, permission *model.Permission) bool {
@@ -134,7 +134,7 @@ func (a *App) HasPermissionToTeam(askingUserId string, teamId string, permission
roles := teamMember.GetRoles()
- if a.CheckIfRolesGrantPermission(roles, permission.Id) {
+ if a.RolesGrantPermission(roles, permission.Id) {
return true
}
@@ -149,7 +149,7 @@ func (a *App) HasPermissionToChannel(askingUserId string, channelId string, perm
channelMember, err := a.GetChannelMember(channelId, askingUserId)
if err == nil {
roles := channelMember.GetRoles()
- if a.CheckIfRolesGrantPermission(roles, permission.Id) {
+ if a.RolesGrantPermission(roles, permission.Id) {
return true
}
}
@@ -168,7 +168,7 @@ func (a *App) HasPermissionToChannelByPost(askingUserId string, postId string, p
if result := <-a.Srv.Store.Channel().GetMemberForPost(postId, askingUserId); result.Err == nil {
channelMember = result.Data.(*model.ChannelMember)
- if a.CheckIfRolesGrantPermission(channelMember.GetRoles(), permission.Id) {
+ if a.RolesGrantPermission(channelMember.GetRoles(), permission.Id) {
return true
}
}
@@ -193,17 +193,21 @@ func (a *App) HasPermissionToUser(askingUserId string, userId string) bool {
return false
}
-func (a *App) CheckIfRolesGrantPermission(roles []string, permissionId string) bool {
- for _, roleId := range roles {
- if role := a.Role(roleId); role == nil {
- l4g.Debug("Bad role in system " + roleId)
- return false
- } else {
- permissions := role.Permissions
- for _, permission := range permissions {
- if permission == permissionId {
- return true
- }
+func (a *App) RolesGrantPermission(roleNames []string, permissionId string) bool {
+ roles, err := a.GetRolesByNames(roleNames)
+ if err != nil {
+ // This should only happen if something is very broken. We can't realistically
+ // recover the situation, so deny permission and log an error.
+ l4g.Error("Failed to get roles from database with role names: " + strings.Join(roleNames, ","))
+ l4g.Error(err)
+ return false
+ }
+
+ for _, role := range roles {
+ permissions := role.Permissions
+ for _, permission := range permissions {
+ if permission == permissionId {
+ return true
}
}
}
diff --git a/app/authorization_test.go b/app/authorization_test.go
index a65fe8333..2127a682e 100644
--- a/app/authorization_test.go
+++ b/app/authorization_test.go
@@ -18,9 +18,9 @@ func TestCheckIfRolesGrantPermission(t *testing.T) {
permissionId string
shouldGrant bool
}{
- {[]string{model.SYSTEM_ADMIN_ROLE_ID}, th.App.Role(model.SYSTEM_ADMIN_ROLE_ID).Permissions[0], true},
+ {[]string{model.SYSTEM_ADMIN_ROLE_ID}, model.PERMISSION_MANAGE_SYSTEM.Id, true},
{[]string{model.SYSTEM_ADMIN_ROLE_ID}, "non-existant-permission", false},
- {[]string{model.CHANNEL_USER_ROLE_ID}, th.App.Role(model.CHANNEL_USER_ROLE_ID).Permissions[0], true},
+ {[]string{model.CHANNEL_USER_ROLE_ID}, model.PERMISSION_READ_CHANNEL.Id, true},
{[]string{model.CHANNEL_USER_ROLE_ID}, model.PERMISSION_MANAGE_SYSTEM.Id, false},
{[]string{model.SYSTEM_ADMIN_ROLE_ID, model.CHANNEL_USER_ROLE_ID}, model.PERMISSION_MANAGE_SYSTEM.Id, true},
{[]string{model.CHANNEL_USER_ROLE_ID, model.SYSTEM_ADMIN_ROLE_ID}, model.PERMISSION_MANAGE_SYSTEM.Id, true},
@@ -29,7 +29,7 @@ func TestCheckIfRolesGrantPermission(t *testing.T) {
}
for testnum, testcase := range cases {
- if th.App.CheckIfRolesGrantPermission(testcase.roles, testcase.permissionId) != testcase.shouldGrant {
+ if th.App.RolesGrantPermission(testcase.roles, testcase.permissionId) != testcase.shouldGrant {
t.Fatal("Failed test case ", testnum)
}
}
diff --git a/app/channel.go b/app/channel.go
index 0054fe14b..c588ebda9 100644
--- a/app/channel.go
+++ b/app/channel.go
@@ -431,6 +431,10 @@ func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles
return nil, err
}
+ if err := a.CheckRolesExist(strings.Fields(newRoles)); err != nil {
+ return nil, err
+ }
+
member.Roles = newRoles
if result := <-a.Srv.Store.Channel().UpdateMember(member); result.Err != nil {
diff --git a/app/import_test.go b/app/import_test.go
index 6a284f63d..be2befd82 100644
--- a/app/import_test.go
+++ b/app/import_test.go
@@ -411,10 +411,6 @@ func TestImportValidateUserImportData(t *testing.T) {
}
data.Position = ptrStr("The Boss")
- data.Roles = ptrStr("system_user wat")
- if err := validateUserImportData(&data); err == nil {
- t.Fatal("Validation should have failed due to too unrecognised role.")
- }
data.Roles = nil
if err := validateUserImportData(&data); err != nil {
t.Fatal("Validation failed but should have been valid.")
@@ -478,12 +474,6 @@ func TestImportValidateUserTeamsImportData(t *testing.T) {
}
data[0].Name = ptrStr("teamname")
- // Invalid Roles
- data[0].Roles = ptrStr("wtf")
- if err := validateUserTeamsImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid roles.")
- }
-
// Valid (nil roles)
data[0].Roles = nil
if err := validateUserTeamsImportData(&data); err != nil {
@@ -516,12 +506,6 @@ func TestImportValidateUserChannelsImportData(t *testing.T) {
}
data[0].Name = ptrStr("channelname")
- // Invalid Roles
- data[0].Roles = ptrStr("wtf")
- if err := validateUserChannelsImportData(&data); err == nil {
- t.Fatal("Should have failed due to invalid roles.")
- }
-
// Valid (nil roles)
data[0].Roles = nil
if err := validateUserChannelsImportData(&data); err != nil {
diff --git a/app/post.go b/app/post.go
index bf4725e77..fc42a6b6b 100644
--- a/app/post.go
+++ b/app/post.go
@@ -127,7 +127,7 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo
if utils.IsLicensed() && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly &&
!post.IsSystemMessage() &&
channel.Name == model.DEFAULT_CHANNEL &&
- !a.CheckIfRolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) {
+ !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) {
return nil, model.NewAppError("createPost", "api.post.create_post.town_square_read_only", nil, "", http.StatusForbidden)
}
diff --git a/app/role.go b/app/role.go
index 5f39dd623..c99d8365b 100644
--- a/app/role.go
+++ b/app/role.go
@@ -1,19 +1,91 @@
-// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
import (
+ "reflect"
+
"github.com/mattermost/mattermost-server/model"
- "github.com/mattermost/mattermost-server/utils"
+ "net/http"
)
-func (a *App) Role(id string) *model.Role {
- return a.roles[id]
+func (a *App) GetRole(id string) (*model.Role, *model.AppError) {
+ if result := <-a.Srv.Store.Role().Get(id); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Role), nil
+ }
+}
+
+func (a *App) GetRoleByName(name string) (*model.Role, *model.AppError) {
+ if result := <-a.Srv.Store.Role().GetByName(name); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Role), nil
+ }
+}
+
+func (a *App) GetRolesByNames(names []string) ([]*model.Role, *model.AppError) {
+ if result := <-a.Srv.Store.Role().GetByNames(names); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.Role), nil
+ }
+}
+
+func (a *App) PatchRole(role *model.Role, patch *model.RolePatch) (*model.Role, *model.AppError) {
+ // If patch is a no-op then short-circuit the store.
+ if patch.Permissions != nil && reflect.DeepEqual(*patch.Permissions, role.Permissions) {
+ return role, nil
+ }
+
+ role.Patch(patch)
+ role, err := a.UpdateRole(role)
+ if err != nil {
+ return nil, err
+ }
+
+ return role, err
}
-// Updates the roles based on the app config and the global license check. You may need to invoke
-// this when license changes are made.
-func (a *App) SetDefaultRolesBasedOnConfig() {
- a.roles = utils.DefaultRolesBasedOnConfig(a.Config())
+func (a *App) UpdateRole(role *model.Role) (*model.Role, *model.AppError) {
+ if result := <-a.Srv.Store.Role().Save(role); result.Err != nil {
+ return nil, result.Err
+ } else {
+ a.sendUpdatedRoleEvent(role)
+
+ return role, nil
+ }
+}
+
+func (a *App) CheckRolesExist(roleNames []string) *model.AppError {
+ roles, err := a.GetRolesByNames(roleNames)
+ if err != nil {
+ return err
+ }
+
+ for _, name := range roleNames {
+ nameFound := false
+ for _, role := range roles {
+ if name == role.Name {
+ nameFound = true
+ break
+ }
+ }
+ if !nameFound {
+ return model.NewAppError("CheckRolesExist", "app.role.check_roles_exist.role_not_found", nil, "role="+name, http.StatusBadRequest)
+ }
+ }
+
+ return nil
+}
+
+func (a *App) sendUpdatedRoleEvent(role *model.Role) {
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ROLE_UPDATED, "", "", "", nil)
+ message.Add("role", role.ToJson())
+
+ a.Go(func() {
+ a.Publish(message)
+ })
}
diff --git a/app/team.go b/app/team.go
index 71eb00569..95d9895ec 100644
--- a/app/team.go
+++ b/app/team.go
@@ -157,6 +157,10 @@ func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles strin
return nil, err
}
+ if err := a.CheckRolesExist(strings.Fields(newRoles)); err != nil {
+ return nil, err
+ }
+
member.Roles = newRoles
if result := <-a.Srv.Store.Team().UpdateMember(member); result.Err != nil {
diff --git a/app/user.go b/app/user.go
index 64e49e293..156503fb0 100644
--- a/app/user.go
+++ b/app/user.go
@@ -1230,6 +1230,10 @@ func (a *App) UpdateUserRoles(userId string, newRoles string, sendWebSocketEvent
return nil, err
}
+ if err := a.CheckRolesExist(strings.Fields(newRoles)); err != nil {
+ return nil, err
+ }
+
user.Roles = newRoles
uchan := a.Srv.Store.User().Update(user, true)
schan := a.Srv.Store.Session().UpdateRoles(user.Id, newRoles)
diff --git a/cmd/platform/server.go b/cmd/platform/server.go
index d289898da..cfcefbba8 100644
--- a/cmd/platform/server.go
+++ b/cmd/platform/server.go
@@ -78,6 +78,8 @@ func runServer(configFileLocation string, disableConfigWatch bool) {
a.LoadLicense()
}
+ a.DoAdvancedPermissionsMigration()
+
a.InitPlugins(*a.Config().PluginSettings.Directory, *a.Config().PluginSettings.ClientDirectory, nil)
a.AddConfigListener(func(prevCfg, cfg *model.Config) {
if *cfg.PluginSettings.Enable {
diff --git a/i18n/en.json b/i18n/en.json
index 88df06f37..606b61181 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -2343,10 +2343,18 @@
"translation": "Your email address for {{.TeamDisplayName}} has been changed to {{.NewEmail}}.<br>If you did not make this change, please contact the system administrator."
},
{
+ "id": "app.role.check_roles_exist.role_not_found",
+ "translation": "The provided role does not exist"
+ },
+ {
"id": "api.templates.email_change_body.title",
"translation": "You updated your email"
},
{
+ "id": "store.sql_role.save.invalid_role.app_error",
+ "translation": "The role was not valid"
+ },
+ {
"id": "api.templates.email_change_subject",
"translation": "[{{ .SiteName }}] Your email address has changed"
},
@@ -6423,6 +6431,26 @@
"translation": "Unable to save reaction"
},
{
+ "id": "store.sql_role.save.insert.app_error",
+ "translation": "Unable to save new role"
+ },
+ {
+ "id": "store.sql_role.save.update.app_error",
+ "translation": "Unable to update role"
+ },
+ {
+ "id": "store.sql_role.get.app_error",
+ "translation": "Unable to get role"
+ },
+ {
+ "id": "store.sql_role.get_by_name.app_error",
+ "translation": "Unable to get role"
+ },
+ {
+ "id": "store.sql_role.get_by_names.app_error",
+ "translation": "Unable to get roles"
+ },
+ {
"id": "store.sql_session.analytics_session_count.app_error",
"translation": "We couldn't count the sessions"
},
diff --git a/model/client4.go b/model/client4.go
index 0694ecbdf..55179bdf9 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -306,6 +306,10 @@ func (c *Client4) GetJobsRoute() string {
return fmt.Sprintf("/jobs")
}
+func (c *Client4) GetRolesRoute() string {
+ return fmt.Sprintf("/roles")
+}
+
func (c *Client4) GetAnalyticsRoute() string {
return fmt.Sprintf("/analytics")
}
@@ -3204,6 +3208,48 @@ func (c *Client4) CancelJob(jobId string) (bool, *Response) {
}
}
+// Roles Section
+
+// GetRole gets a single role by ID.
+func (c *Client4) GetRole(id string) (*Role, *Response) {
+ if r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/%v", id), ""); err != nil {
+ return nil, BuildErrorResponse(r, err)
+ } else {
+ defer closeBody(r)
+ return RoleFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// GetRoleByName gets a single role by Name.
+func (c *Client4) GetRoleByName(name string) (*Role, *Response) {
+ if r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/name/%v", name), ""); err != nil {
+ return nil, BuildErrorResponse(r, err)
+ } else {
+ defer closeBody(r)
+ return RoleFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// GetRolesByNames returns a list of roles based on the provided role names.
+func (c *Client4) GetRolesByNames(roleNames []string) ([]*Role, *Response) {
+ if r, err := c.DoApiPost(c.GetRolesRoute()+"/names", ArrayToJson(roleNames)); err != nil {
+ return nil, BuildErrorResponse(r, err)
+ } else {
+ defer closeBody(r)
+ return RoleListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// PatchRole partially updates a role in the system. Any missing fields are not updated.
+func (c *Client4) PatchRole(roleId string, patch *RolePatch) (*Role, *Response) {
+ if r, err := c.DoApiPut(c.GetRolesRoute()+fmt.Sprintf("/%v/patch", roleId), patch.ToJson()); err != nil {
+ return nil, BuildErrorResponse(r, err)
+ } else {
+ defer closeBody(r)
+ return RoleFromJson(r.Body), BuildResponse(r)
+ }
+}
+
// Plugin Section
// UploadPlugin takes an io.Reader stream pointing to the contents of a .tar.gz plugin.
diff --git a/model/cluster_message.go b/model/cluster_message.go
index a6dec2e7f..9cf0e4d55 100644
--- a/model/cluster_message.go
+++ b/model/cluster_message.go
@@ -21,6 +21,7 @@ const (
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL = "inv_channel"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER = "inv_user"
CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER = "clear_session_user"
+ CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES = "inv_roles"
CLUSTER_SEND_BEST_EFFORT = "best_effort"
CLUSTER_SEND_RELIABLE = "reliable"
diff --git a/model/authorization.go b/model/permission.go
index 9f4e36eab..0dc09f49a 100644
--- a/model/authorization.go
+++ b/model/permission.go
@@ -3,17 +3,17 @@
package model
+const (
+ PERMISSION_SCOPE_SYSTEM = "system_scope"
+ PERMISSION_SCOPE_TEAM = "team_scope"
+ PERMISSION_SCOPE_CHANNEL = "channel_scope"
+)
+
type Permission struct {
Id string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
-}
-
-type Role struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Description string `json:"description"`
- Permissions []string `json:"permissions"`
+ Scope string `json:"scope"`
}
var PERMISSION_INVITE_USER *Permission
@@ -64,459 +64,355 @@ var PERMISSION_CREATE_USER_ACCESS_TOKEN *Permission
var PERMISSION_READ_USER_ACCESS_TOKEN *Permission
var PERMISSION_REVOKE_USER_ACCESS_TOKEN *Permission
-// General permission that encompases all system admin functions
+// General permission that encompasses all system admin functions
// in the future this could be broken up to allow access to some
// admin functions but not others
var PERMISSION_MANAGE_SYSTEM *Permission
-const (
- SYSTEM_USER_ROLE_ID = "system_user"
- SYSTEM_ADMIN_ROLE_ID = "system_admin"
- SYSTEM_POST_ALL_ROLE_ID = "system_post_all"
- SYSTEM_POST_ALL_PUBLIC_ROLE_ID = "system_post_all_public"
- SYSTEM_USER_ACCESS_TOKEN_ROLE_ID = "system_user_access_token"
-
- TEAM_USER_ROLE_ID = "team_user"
- TEAM_ADMIN_ROLE_ID = "team_admin"
- TEAM_POST_ALL_ROLE_ID = "team_post_all"
- TEAM_POST_ALL_PUBLIC_ROLE_ID = "team_post_all_public"
-
- CHANNEL_USER_ROLE_ID = "channel_user"
- CHANNEL_ADMIN_ROLE_ID = "channel_admin"
- CHANNEL_GUEST_ROLE_ID = "guest"
-)
+var ALL_PERMISSIONS []*Permission
func initializePermissions() {
PERMISSION_INVITE_USER = &Permission{
"invite_user",
"authentication.permissions.team_invite_user.name",
"authentication.permissions.team_invite_user.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_ADD_USER_TO_TEAM = &Permission{
"add_user_to_team",
"authentication.permissions.add_user_to_team.name",
"authentication.permissions.add_user_to_team.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_USE_SLASH_COMMANDS = &Permission{
"use_slash_commands",
"authentication.permissions.team_use_slash_commands.name",
"authentication.permissions.team_use_slash_commands.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_MANAGE_SLASH_COMMANDS = &Permission{
"manage_slash_commands",
"authentication.permissions.manage_slash_commands.name",
"authentication.permissions.manage_slash_commands.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS = &Permission{
"manage_others_slash_commands",
"authentication.permissions.manage_others_slash_commands.name",
"authentication.permissions.manage_others_slash_commands.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_CREATE_PUBLIC_CHANNEL = &Permission{
"create_public_channel",
"authentication.permissions.create_public_channel.name",
"authentication.permissions.create_public_channel.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_CREATE_PRIVATE_CHANNEL = &Permission{
"create_private_channel",
"authentication.permissions.create_private_channel.name",
"authentication.permissions.create_private_channel.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS = &Permission{
"manage_public_channel_members",
"authentication.permissions.manage_public_channel_members.name",
"authentication.permissions.manage_public_channel_members.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS = &Permission{
"manage_private_channel_members",
"authentication.permissions.manage_private_channel_members.name",
"authentication.permissions.manage_private_channel_members.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE = &Permission{
"assign_system_admin_role",
"authentication.permissions.assign_system_admin_role.name",
"authentication.permissions.assign_system_admin_role.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_MANAGE_ROLES = &Permission{
"manage_roles",
"authentication.permissions.manage_roles.name",
"authentication.permissions.manage_roles.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_MANAGE_TEAM_ROLES = &Permission{
"manage_team_roles",
"authentication.permissions.manage_team_roles.name",
"authentication.permissions.manage_team_roles.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_MANAGE_CHANNEL_ROLES = &Permission{
"manage_channel_roles",
"authentication.permissions.manage_channel_roles.name",
"authentication.permissions.manage_channel_roles.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_MANAGE_SYSTEM = &Permission{
"manage_system",
"authentication.permissions.manage_system.name",
"authentication.permissions.manage_system.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_CREATE_DIRECT_CHANNEL = &Permission{
"create_direct_channel",
"authentication.permissions.create_direct_channel.name",
"authentication.permissions.create_direct_channel.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_CREATE_GROUP_CHANNEL = &Permission{
"create_group_channel",
"authentication.permissions.create_group_channel.name",
"authentication.permissions.create_group_channel.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = &Permission{
- "manage__publicchannel_properties",
+ "manage_public_channel_properties",
"authentication.permissions.manage_public_channel_properties.name",
"authentication.permissions.manage_public_channel_properties.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES = &Permission{
"manage_private_channel_properties",
"authentication.permissions.manage_private_channel_properties.name",
"authentication.permissions.manage_private_channel_properties.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_LIST_TEAM_CHANNELS = &Permission{
"list_team_channels",
"authentication.permissions.list_team_channels.name",
"authentication.permissions.list_team_channels.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_JOIN_PUBLIC_CHANNELS = &Permission{
"join_public_channels",
"authentication.permissions.join_public_channels.name",
"authentication.permissions.join_public_channels.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_DELETE_PUBLIC_CHANNEL = &Permission{
"delete_public_channel",
"authentication.permissions.delete_public_channel.name",
"authentication.permissions.delete_public_channel.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_DELETE_PRIVATE_CHANNEL = &Permission{
"delete_private_channel",
"authentication.permissions.delete_private_channel.name",
"authentication.permissions.delete_private_channel.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_EDIT_OTHER_USERS = &Permission{
"edit_other_users",
"authentication.permissions.edit_other_users.name",
"authentication.permissions.edit_other_users.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_READ_CHANNEL = &Permission{
"read_channel",
"authentication.permissions.read_channel.name",
"authentication.permissions.read_channel.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_READ_PUBLIC_CHANNEL = &Permission{
"read_public_channel",
"authentication.permissions.read_public_channel.name",
"authentication.permissions.read_public_channel.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_PERMANENT_DELETE_USER = &Permission{
"permanent_delete_user",
"authentication.permissions.permanent_delete_user.name",
"authentication.permissions.permanent_delete_user.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_UPLOAD_FILE = &Permission{
"upload_file",
"authentication.permissions.upload_file.name",
"authentication.permissions.upload_file.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_GET_PUBLIC_LINK = &Permission{
"get_public_link",
"authentication.permissions.get_public_link.name",
"authentication.permissions.get_public_link.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_MANAGE_WEBHOOKS = &Permission{
"manage_webhooks",
"authentication.permissions.manage_webhooks.name",
"authentication.permissions.manage_webhooks.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_MANAGE_OTHERS_WEBHOOKS = &Permission{
"manage_others_webhooks",
"authentication.permissions.manage_others_webhooks.name",
"authentication.permissions.manage_others_webhooks.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_MANAGE_OAUTH = &Permission{
"manage_oauth",
"authentication.permissions.manage_oauth.name",
"authentication.permissions.manage_oauth.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH = &Permission{
"manage_sytem_wide_oauth",
"authentication.permissions.manage_sytem_wide_oauth.name",
"authentication.permissions.manage_sytem_wide_oauth.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_CREATE_POST = &Permission{
"create_post",
"authentication.permissions.create_post.name",
"authentication.permissions.create_post.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_CREATE_POST_PUBLIC = &Permission{
"create_post_public",
"authentication.permissions.create_post_public.name",
"authentication.permissions.create_post_public.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_EDIT_POST = &Permission{
"edit_post",
"authentication.permissions.edit_post.name",
"authentication.permissions.edit_post.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_EDIT_OTHERS_POSTS = &Permission{
"edit_others_posts",
"authentication.permissions.edit_others_posts.name",
"authentication.permissions.edit_others_posts.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_DELETE_POST = &Permission{
"delete_post",
"authentication.permissions.delete_post.name",
"authentication.permissions.delete_post.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_DELETE_OTHERS_POSTS = &Permission{
"delete_others_posts",
"authentication.permissions.delete_others_posts.name",
"authentication.permissions.delete_others_posts.description",
+ PERMISSION_SCOPE_CHANNEL,
}
PERMISSION_REMOVE_USER_FROM_TEAM = &Permission{
"remove_user_from_team",
"authentication.permissions.remove_user_from_team.name",
"authentication.permissions.remove_user_from_team.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_CREATE_TEAM = &Permission{
"create_team",
"authentication.permissions.create_team.name",
"authentication.permissions.create_team.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_MANAGE_TEAM = &Permission{
"manage_team",
"authentication.permissions.manage_team.name",
"authentication.permissions.manage_team.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_IMPORT_TEAM = &Permission{
"import_team",
"authentication.permissions.import_team.name",
"authentication.permissions.import_team.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_VIEW_TEAM = &Permission{
"view_team",
"authentication.permissions.view_team.name",
"authentication.permissions.view_team.description",
+ PERMISSION_SCOPE_TEAM,
}
PERMISSION_LIST_USERS_WITHOUT_TEAM = &Permission{
"list_users_without_team",
"authentication.permissions.list_users_without_team.name",
"authentication.permissions.list_users_without_team.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_CREATE_USER_ACCESS_TOKEN = &Permission{
"create_user_access_token",
"authentication.permissions.create_user_access_token.name",
"authentication.permissions.create_user_access_token.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_READ_USER_ACCESS_TOKEN = &Permission{
"read_user_access_token",
"authentication.permissions.read_user_access_token.name",
"authentication.permissions.read_user_access_token.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_REVOKE_USER_ACCESS_TOKEN = &Permission{
"revoke_user_access_token",
"authentication.permissions.revoke_user_access_token.name",
"authentication.permissions.revoke_user_access_token.description",
+ PERMISSION_SCOPE_SYSTEM,
}
PERMISSION_MANAGE_JOBS = &Permission{
"manage_jobs",
"authentication.permisssions.manage_jobs.name",
"authentication.permisssions.manage_jobs.description",
- }
-}
-
-var DefaultRoles map[string]*Role
-
-func initializeDefaultRoles() {
- DefaultRoles = make(map[string]*Role)
-
- DefaultRoles[CHANNEL_USER_ROLE_ID] = &Role{
- "channel_user",
- "authentication.roles.channel_user.name",
- "authentication.roles.channel_user.description",
- []string{
- PERMISSION_READ_CHANNEL.Id,
- PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
- PERMISSION_UPLOAD_FILE.Id,
- PERMISSION_GET_PUBLIC_LINK.Id,
- PERMISSION_CREATE_POST.Id,
- PERMISSION_EDIT_POST.Id,
- PERMISSION_USE_SLASH_COMMANDS.Id,
- },
- }
-
- DefaultRoles[CHANNEL_ADMIN_ROLE_ID] = &Role{
- "channel_admin",
- "authentication.roles.channel_admin.name",
- "authentication.roles.channel_admin.description",
- []string{
- PERMISSION_MANAGE_CHANNEL_ROLES.Id,
- },
- }
-
- DefaultRoles[CHANNEL_GUEST_ROLE_ID] = &Role{
- "guest",
- "authentication.roles.global_guest.name",
- "authentication.roles.global_guest.description",
- []string{},
- }
-
- DefaultRoles[TEAM_USER_ROLE_ID] = &Role{
- "team_user",
- "authentication.roles.team_user.name",
- "authentication.roles.team_user.description",
- []string{
- PERMISSION_LIST_TEAM_CHANNELS.Id,
- PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
- PERMISSION_READ_PUBLIC_CHANNEL.Id,
- PERMISSION_VIEW_TEAM.Id,
- },
+ PERMISSION_SCOPE_SYSTEM,
}
- DefaultRoles[TEAM_POST_ALL_ROLE_ID] = &Role{
- "team_post_all",
- "authentication.roles.team_post_all.name",
- "authentication.roles.team_post_all.description",
- []string{
- PERMISSION_CREATE_POST.Id,
- },
+ ALL_PERMISSIONS = []*Permission{
+ PERMISSION_INVITE_USER,
+ PERMISSION_ADD_USER_TO_TEAM,
+ PERMISSION_USE_SLASH_COMMANDS,
+ PERMISSION_MANAGE_SLASH_COMMANDS,
+ PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS,
+ PERMISSION_CREATE_PUBLIC_CHANNEL,
+ PERMISSION_CREATE_PRIVATE_CHANNEL,
+ PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS,
+ PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS,
+ PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE,
+ PERMISSION_MANAGE_ROLES,
+ PERMISSION_MANAGE_TEAM_ROLES,
+ PERMISSION_MANAGE_CHANNEL_ROLES,
+ PERMISSION_CREATE_DIRECT_CHANNEL,
+ PERMISSION_CREATE_GROUP_CHANNEL,
+ PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES,
+ PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES,
+ PERMISSION_LIST_TEAM_CHANNELS,
+ PERMISSION_JOIN_PUBLIC_CHANNELS,
+ PERMISSION_DELETE_PUBLIC_CHANNEL,
+ PERMISSION_DELETE_PRIVATE_CHANNEL,
+ PERMISSION_EDIT_OTHER_USERS,
+ PERMISSION_READ_CHANNEL,
+ PERMISSION_READ_PUBLIC_CHANNEL,
+ PERMISSION_PERMANENT_DELETE_USER,
+ PERMISSION_UPLOAD_FILE,
+ PERMISSION_GET_PUBLIC_LINK,
+ PERMISSION_MANAGE_WEBHOOKS,
+ PERMISSION_MANAGE_OTHERS_WEBHOOKS,
+ PERMISSION_MANAGE_OAUTH,
+ PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH,
+ PERMISSION_CREATE_POST,
+ PERMISSION_CREATE_POST_PUBLIC,
+ PERMISSION_EDIT_POST,
+ PERMISSION_EDIT_OTHERS_POSTS,
+ PERMISSION_DELETE_POST,
+ PERMISSION_DELETE_OTHERS_POSTS,
+ PERMISSION_REMOVE_USER_FROM_TEAM,
+ PERMISSION_CREATE_TEAM,
+ PERMISSION_MANAGE_TEAM,
+ PERMISSION_IMPORT_TEAM,
+ PERMISSION_VIEW_TEAM,
+ PERMISSION_LIST_USERS_WITHOUT_TEAM,
+ PERMISSION_MANAGE_JOBS,
+ PERMISSION_CREATE_USER_ACCESS_TOKEN,
+ PERMISSION_READ_USER_ACCESS_TOKEN,
+ PERMISSION_REVOKE_USER_ACCESS_TOKEN,
+ PERMISSION_MANAGE_SYSTEM,
}
-
- DefaultRoles[TEAM_POST_ALL_PUBLIC_ROLE_ID] = &Role{
- "team_post_all_public",
- "authentication.roles.team_post_all_public.name",
- "authentication.roles.team_post_all_public.description",
- []string{
- PERMISSION_CREATE_POST_PUBLIC.Id,
- },
- }
-
- DefaultRoles[TEAM_ADMIN_ROLE_ID] = &Role{
- "team_admin",
- "authentication.roles.team_admin.name",
- "authentication.roles.team_admin.description",
- []string{
- PERMISSION_EDIT_OTHERS_POSTS.Id,
- PERMISSION_REMOVE_USER_FROM_TEAM.Id,
- PERMISSION_MANAGE_TEAM.Id,
- PERMISSION_IMPORT_TEAM.Id,
- PERMISSION_MANAGE_TEAM_ROLES.Id,
- PERMISSION_MANAGE_CHANNEL_ROLES.Id,
- PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
- PERMISSION_MANAGE_SLASH_COMMANDS.Id,
- PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
- PERMISSION_MANAGE_WEBHOOKS.Id,
- },
- }
-
- DefaultRoles[SYSTEM_USER_ROLE_ID] = &Role{
- "system_user",
- "authentication.roles.global_user.name",
- "authentication.roles.global_user.description",
- []string{
- PERMISSION_CREATE_DIRECT_CHANNEL.Id,
- PERMISSION_CREATE_GROUP_CHANNEL.Id,
- PERMISSION_PERMANENT_DELETE_USER.Id,
- },
- }
-
- DefaultRoles[SYSTEM_POST_ALL_ROLE_ID] = &Role{
- "system_post_all",
- "authentication.roles.system_post_all.name",
- "authentication.roles.system_post_all.description",
- []string{
- PERMISSION_CREATE_POST.Id,
- },
- }
-
- DefaultRoles[SYSTEM_POST_ALL_PUBLIC_ROLE_ID] = &Role{
- "system_post_all_public",
- "authentication.roles.system_post_all_public.name",
- "authentication.roles.system_post_all_public.description",
- []string{
- PERMISSION_CREATE_POST_PUBLIC.Id,
- },
- }
-
- DefaultRoles[SYSTEM_USER_ACCESS_TOKEN_ROLE_ID] = &Role{
- "system_user_access_token",
- "authentication.roles.system_user_access_token.name",
- "authentication.roles.system_user_access_token.description",
- []string{
- PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
- PERMISSION_READ_USER_ACCESS_TOKEN.Id,
- PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
- },
- }
-
- DefaultRoles[SYSTEM_ADMIN_ROLE_ID] = &Role{
- "system_admin",
- "authentication.roles.global_admin.name",
- "authentication.roles.global_admin.description",
- // System admins can do anything channel and team admins can do
- // plus everything members of teams and channels can do to all teams
- // and channels on the system
- append(
- append(
- append(
- append(
- []string{
- PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE.Id,
- PERMISSION_MANAGE_SYSTEM.Id,
- PERMISSION_MANAGE_ROLES.Id,
- PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
- PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
- PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
- PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
- PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
- PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
- PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
- PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
- PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH.Id,
- PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
- PERMISSION_EDIT_OTHER_USERS.Id,
- PERMISSION_MANAGE_OAUTH.Id,
- PERMISSION_INVITE_USER.Id,
- PERMISSION_DELETE_POST.Id,
- PERMISSION_DELETE_OTHERS_POSTS.Id,
- PERMISSION_CREATE_TEAM.Id,
- PERMISSION_ADD_USER_TO_TEAM.Id,
- PERMISSION_LIST_USERS_WITHOUT_TEAM.Id,
- PERMISSION_MANAGE_JOBS.Id,
- PERMISSION_CREATE_POST_PUBLIC.Id,
- PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
- PERMISSION_READ_USER_ACCESS_TOKEN.Id,
- PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
- },
- DefaultRoles[TEAM_USER_ROLE_ID].Permissions...,
- ),
- DefaultRoles[CHANNEL_USER_ROLE_ID].Permissions...,
- ),
- DefaultRoles[TEAM_ADMIN_ROLE_ID].Permissions...,
- ),
- DefaultRoles[CHANNEL_ADMIN_ROLE_ID].Permissions...,
- ),
- }
-}
-
-func RoleIdsToString(roles []string) string {
- output := ""
- for _, role := range roles {
- output += role + ", "
- }
-
- if output == "" {
- return "[<NO ROLES>]"
- }
-
- return output[:len(output)-1]
}
func init() {
initializePermissions()
- initializeDefaultRoles()
}
diff --git a/model/permission_test.go b/model/permission_test.go
new file mode 100644
index 000000000..cef72af90
--- /dev/null
+++ b/model/permission_test.go
@@ -0,0 +1,18 @@
+package model
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// This is a test to ensure that we don't accidentally add more permissions than can fit
+// in the database column for role permissions.
+func TestPermissionsLength(t *testing.T) {
+ permissionsString := ""
+ for _, permission := range ALL_PERMISSIONS {
+ permissionsString += " " + permission.Id
+ }
+
+ assert.True(t, len(permissionsString) < 4096)
+}
diff --git a/model/role.go b/model/role.go
new file mode 100644
index 000000000..254513ae0
--- /dev/null
+++ b/model/role.go
@@ -0,0 +1,310 @@
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "encoding/json"
+ "io"
+ "strings"
+)
+
+const (
+ SYSTEM_USER_ROLE_ID = "system_user"
+ SYSTEM_ADMIN_ROLE_ID = "system_admin"
+ SYSTEM_POST_ALL_ROLE_ID = "system_post_all"
+ SYSTEM_POST_ALL_PUBLIC_ROLE_ID = "system_post_all_public"
+ SYSTEM_USER_ACCESS_TOKEN_ROLE_ID = "system_user_access_token"
+
+ TEAM_USER_ROLE_ID = "team_user"
+ TEAM_ADMIN_ROLE_ID = "team_admin"
+ TEAM_POST_ALL_ROLE_ID = "team_post_all"
+ TEAM_POST_ALL_PUBLIC_ROLE_ID = "team_post_all_public"
+
+ CHANNEL_USER_ROLE_ID = "channel_user"
+ CHANNEL_ADMIN_ROLE_ID = "channel_admin"
+
+ ROLE_NAME_MAX_LENGTH = 64
+ ROLE_DISPLAY_NAME_MAX_LENGTH = 128
+ ROLE_DESCRIPTION_MAX_LENGTH = 1024
+)
+
+type Role struct {
+ Id string `json:"id"`
+ Name string `json:"name"`
+ DisplayName string `json:"display_name"`
+ Description string `json:"description"`
+ Permissions []string `json:"permissions"`
+ SchemeManaged bool `json:"scheme_managed"`
+}
+
+type RolePatch struct {
+ Permissions *[]string `json:"permissions"`
+}
+
+func (role *Role) ToJson() string {
+ b, _ := json.Marshal(role)
+ return string(b)
+}
+
+func RoleFromJson(data io.Reader) *Role {
+ var role *Role
+ json.NewDecoder(data).Decode(&role)
+ return role
+}
+
+func RoleListToJson(r []*Role) string {
+ b, _ := json.Marshal(r)
+ return string(b)
+}
+
+func RoleListFromJson(data io.Reader) []*Role {
+ var roles []*Role
+ json.NewDecoder(data).Decode(&roles)
+ return roles
+}
+
+func (r *RolePatch) ToJson() string {
+ b, _ := json.Marshal(r)
+ return string(b)
+}
+
+func RolePatchFromJson(data io.Reader) *RolePatch {
+ var rolePatch *RolePatch
+ json.NewDecoder(data).Decode(&rolePatch)
+ return rolePatch
+}
+
+func (o *Role) Patch(patch *RolePatch) {
+ if patch.Permissions != nil {
+ o.Permissions = *patch.Permissions
+ }
+}
+
+func (role *Role) IsValid() bool {
+ if len(role.Id) != 26 {
+ return false
+ }
+
+ return role.IsValidWithoutId()
+}
+
+func (role *Role) IsValidWithoutId() bool {
+ if !IsValidRoleName(role.Name) {
+ return false
+ }
+
+ if len(role.DisplayName) == 0 || len(role.DisplayName) > ROLE_DISPLAY_NAME_MAX_LENGTH {
+ return false
+ }
+
+ if len(role.Description) > ROLE_DESCRIPTION_MAX_LENGTH {
+ return false
+ }
+
+ for _, permission := range role.Permissions {
+ permissionValidated := false
+ for _, p := range ALL_PERMISSIONS {
+ if permission == p.Id {
+ permissionValidated = true
+ break
+ }
+ }
+
+ if !permissionValidated {
+ return false
+ }
+ }
+
+ return true
+}
+
+func IsValidRoleName(roleName string) bool {
+ if len(roleName) <= 0 || len(roleName) > ROLE_NAME_MAX_LENGTH {
+ return false
+ }
+
+ if strings.TrimLeft(roleName, "abcdefghijklmnopqrstuvwxyz0123456789_") != "" {
+ return false
+ }
+
+ return true
+}
+
+func MakeDefaultRoles() map[string]*Role {
+ roles := make(map[string]*Role)
+
+ roles[CHANNEL_USER_ROLE_ID] = &Role{
+ Name: "channel_user",
+ DisplayName: "authentication.roles.channel_user.name",
+ Description: "authentication.roles.channel_user.description",
+ Permissions: []string{
+ PERMISSION_READ_CHANNEL.Id,
+ PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
+ PERMISSION_UPLOAD_FILE.Id,
+ PERMISSION_GET_PUBLIC_LINK.Id,
+ PERMISSION_CREATE_POST.Id,
+ PERMISSION_EDIT_POST.Id,
+ PERMISSION_USE_SLASH_COMMANDS.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[CHANNEL_ADMIN_ROLE_ID] = &Role{
+ Name: "channel_admin",
+ DisplayName: "authentication.roles.channel_admin.name",
+ Description: "authentication.roles.channel_admin.description",
+ Permissions: []string{
+ PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[TEAM_USER_ROLE_ID] = &Role{
+ Name: "team_user",
+ DisplayName: "authentication.roles.team_user.name",
+ Description: "authentication.roles.team_user.description",
+ Permissions: []string{
+ PERMISSION_LIST_TEAM_CHANNELS.Id,
+ PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
+ PERMISSION_READ_PUBLIC_CHANNEL.Id,
+ PERMISSION_VIEW_TEAM.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[TEAM_POST_ALL_ROLE_ID] = &Role{
+ Name: "team_post_all",
+ DisplayName: "authentication.roles.team_post_all.name",
+ Description: "authentication.roles.team_post_all.description",
+ Permissions: []string{
+ PERMISSION_CREATE_POST.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[TEAM_POST_ALL_PUBLIC_ROLE_ID] = &Role{
+ Name: "team_post_all_public",
+ DisplayName: "authentication.roles.team_post_all_public.name",
+ Description: "authentication.roles.team_post_all_public.description",
+ Permissions: []string{
+ PERMISSION_CREATE_POST_PUBLIC.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[TEAM_ADMIN_ROLE_ID] = &Role{
+ Name: "team_admin",
+ DisplayName: "authentication.roles.team_admin.name",
+ Description: "authentication.roles.team_admin.description",
+ Permissions: []string{
+ PERMISSION_EDIT_OTHERS_POSTS.Id,
+ PERMISSION_REMOVE_USER_FROM_TEAM.Id,
+ PERMISSION_MANAGE_TEAM.Id,
+ PERMISSION_IMPORT_TEAM.Id,
+ PERMISSION_MANAGE_TEAM_ROLES.Id,
+ PERMISSION_MANAGE_CHANNEL_ROLES.Id,
+ PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
+ PERMISSION_MANAGE_SLASH_COMMANDS.Id,
+ PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
+ PERMISSION_MANAGE_WEBHOOKS.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[SYSTEM_USER_ROLE_ID] = &Role{
+ Name: "system_user",
+ DisplayName: "authentication.roles.global_user.name",
+ Description: "authentication.roles.global_user.description",
+ Permissions: []string{
+ PERMISSION_CREATE_DIRECT_CHANNEL.Id,
+ PERMISSION_CREATE_GROUP_CHANNEL.Id,
+ PERMISSION_PERMANENT_DELETE_USER.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[SYSTEM_POST_ALL_ROLE_ID] = &Role{
+ Name: "system_post_all",
+ DisplayName: "authentication.roles.system_post_all.name",
+ Description: "authentication.roles.system_post_all.description",
+ Permissions: []string{
+ PERMISSION_CREATE_POST.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[SYSTEM_POST_ALL_PUBLIC_ROLE_ID] = &Role{
+ Name: "system_post_all_public",
+ DisplayName: "authentication.roles.system_post_all_public.name",
+ Description: "authentication.roles.system_post_all_public.description",
+ Permissions: []string{
+ PERMISSION_CREATE_POST_PUBLIC.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[SYSTEM_USER_ACCESS_TOKEN_ROLE_ID] = &Role{
+ Name: "system_user_access_token",
+ DisplayName: "authentication.roles.system_user_access_token.name",
+ Description: "authentication.roles.system_user_access_token.description",
+ Permissions: []string{
+ PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
+ PERMISSION_READ_USER_ACCESS_TOKEN.Id,
+ PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
+ },
+ SchemeManaged: true,
+ }
+
+ roles[SYSTEM_ADMIN_ROLE_ID] = &Role{
+ Name: "system_admin",
+ DisplayName: "authentication.roles.global_admin.name",
+ Description: "authentication.roles.global_admin.description",
+ // System admins can do anything channel and team admins can do
+ // plus everything members of teams and channels can do to all teams
+ // and channels on the system
+ Permissions: append(
+ append(
+ append(
+ append(
+ []string{
+ PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE.Id,
+ PERMISSION_MANAGE_SYSTEM.Id,
+ PERMISSION_MANAGE_ROLES.Id,
+ PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
+ PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
+ PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
+ PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
+ PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
+ PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
+ PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
+ PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
+ PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH.Id,
+ PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
+ PERMISSION_EDIT_OTHER_USERS.Id,
+ PERMISSION_MANAGE_OAUTH.Id,
+ PERMISSION_INVITE_USER.Id,
+ PERMISSION_DELETE_POST.Id,
+ PERMISSION_DELETE_OTHERS_POSTS.Id,
+ PERMISSION_CREATE_TEAM.Id,
+ PERMISSION_ADD_USER_TO_TEAM.Id,
+ PERMISSION_LIST_USERS_WITHOUT_TEAM.Id,
+ PERMISSION_MANAGE_JOBS.Id,
+ PERMISSION_CREATE_POST_PUBLIC.Id,
+ PERMISSION_CREATE_USER_ACCESS_TOKEN.Id,
+ PERMISSION_READ_USER_ACCESS_TOKEN.Id,
+ PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id,
+ },
+ roles[TEAM_USER_ROLE_ID].Permissions...,
+ ),
+ roles[CHANNEL_USER_ROLE_ID].Permissions...,
+ ),
+ roles[TEAM_ADMIN_ROLE_ID].Permissions...,
+ ),
+ roles[CHANNEL_ADMIN_ROLE_ID].Permissions...,
+ ),
+ SchemeManaged: true,
+ }
+
+ return roles
+}
diff --git a/model/user.go b/model/user.go
index 4c08eac24..556ebb1f7 100644
--- a/model/user.go
+++ b/model/user.go
@@ -432,7 +432,7 @@ func IsValidUserRoles(userRoles string) bool {
roles := strings.Fields(userRoles)
for _, r := range roles {
- if !isValidRole(r) {
+ if !IsValidRoleName(r) {
return false
}
}
@@ -445,11 +445,6 @@ func IsValidUserRoles(userRoles string) bool {
return true
}
-func isValidRole(roleId string) bool {
- _, ok := DefaultRoles[roleId]
- return ok
-}
-
// Make sure you acually want to use this function. In context.go there are functions to check permissions
// This function should not be used to check permissions.
func (u *User) IsInRole(inRole string) bool {
diff --git a/model/user_test.go b/model/user_test.go
index c91051532..5f97b3ff2 100644
--- a/model/user_test.go
+++ b/model/user_test.go
@@ -263,11 +263,11 @@ func TestCleanUsername(t *testing.T) {
func TestRoles(t *testing.T) {
- if IsValidUserRoles("admin") {
+ if !IsValidUserRoles("team_user") {
t.Fatal()
}
- if IsValidUserRoles("junk") {
+ if IsValidUserRoles("system_admin") {
t.Fatal()
}
diff --git a/model/websocket_message.go b/model/websocket_message.go
index bf2535dc3..d0e8cb039 100644
--- a/model/websocket_message.go
+++ b/model/websocket_message.go
@@ -42,6 +42,7 @@ const (
WEBSOCKET_EVENT_CHANNEL_VIEWED = "channel_viewed"
WEBSOCKET_EVENT_PLUGIN_ACTIVATED = "plugin_activated" // EXPERIMENTAL - SUBJECT TO CHANGE
WEBSOCKET_EVENT_PLUGIN_DEACTIVATED = "plugin_deactivated" // EXPERIMENTAL - SUBJECT TO CHANGE
+ WEBSOCKET_EVENT_ROLE_UPDATED = "role_updated"
)
type WebSocketMessage interface {
diff --git a/store/layered_store.go b/store/layered_store.go
index 65b4670c0..cac0f61d3 100644
--- a/store/layered_store.go
+++ b/store/layered_store.go
@@ -23,6 +23,7 @@ type LayeredStoreDatabaseLayer interface {
type LayeredStore struct {
TmpContext context.Context
ReactionStore ReactionStore
+ RoleStore RoleStore
DatabaseLayer LayeredStoreDatabaseLayer
LocalCacheLayer *LocalCacheSupplier
RedisLayer *RedisSupplier
@@ -37,6 +38,7 @@ func NewLayeredStore(db LayeredStoreDatabaseLayer, metrics einterfaces.MetricsIn
}
store.ReactionStore = &LayeredReactionStore{store}
+ store.RoleStore = &LayeredRoleStore{store}
// Setup the chain
if ENABLE_EXPERIMENTAL_REDIS {
@@ -161,6 +163,10 @@ func (s *LayeredStore) Plugin() PluginStore {
return s.DatabaseLayer.Plugin()
}
+func (s *LayeredStore) Role() RoleStore {
+ return s.RoleStore
+}
+
func (s *LayeredStore) MarkSystemRanUnitTests() {
s.DatabaseLayer.MarkSystemRanUnitTests()
}
@@ -218,3 +224,31 @@ func (s *LayeredReactionStore) PermanentDeleteBatch(endTime int64, limit int64)
return supplier.ReactionPermanentDeleteBatch(s.TmpContext, endTime, limit)
})
}
+
+type LayeredRoleStore struct {
+ *LayeredStore
+}
+
+func (s *LayeredRoleStore) Save(role *model.Role) StoreChannel {
+ return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
+ return supplier.RoleSave(s.TmpContext, role)
+ })
+}
+
+func (s *LayeredRoleStore) Get(roleId string) StoreChannel {
+ return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
+ return supplier.RoleGet(s.TmpContext, roleId)
+ })
+}
+
+func (s *LayeredRoleStore) GetByName(name string) StoreChannel {
+ return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
+ return supplier.RoleGetByName(s.TmpContext, name)
+ })
+}
+
+func (s *LayeredRoleStore) GetByNames(names []string) StoreChannel {
+ return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
+ return supplier.RoleGetByNames(s.TmpContext, names)
+ })
+}
diff --git a/store/layered_store_supplier.go b/store/layered_store_supplier.go
index 841b75a32..482ccd126 100644
--- a/store/layered_store_supplier.go
+++ b/store/layered_store_supplier.go
@@ -31,4 +31,10 @@ type LayeredStoreSupplier interface {
ReactionGetForPost(ctx context.Context, postId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
+
+ // Roles
+ RoleSave(ctx context.Context, role *model.Role, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
+ RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
+ RoleGetByName(ctx context.Context, name string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
+ RoleGetByNames(ctx context.Context, names []string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
}
diff --git a/store/local_cache_supplier.go b/store/local_cache_supplier.go
index 3627c5b39..2343f10a7 100644
--- a/store/local_cache_supplier.go
+++ b/store/local_cache_supplier.go
@@ -13,7 +13,10 @@ import (
const (
REACTION_CACHE_SIZE = 20000
- REACTION_CACHE_SEC = 1800 // 30 minutes
+ REACTION_CACHE_SEC = 30 * 60
+
+ ROLE_CACHE_SIZE = 20000
+ ROLE_CACHE_SEC = 30 * 60
CLEAR_CACHE_MESSAGE_DATA = ""
)
@@ -21,6 +24,7 @@ const (
type LocalCacheSupplier struct {
next LayeredStoreSupplier
reactionCache *utils.Cache
+ roleCache *utils.Cache
metrics einterfaces.MetricsInterface
cluster einterfaces.ClusterInterface
}
@@ -28,12 +32,14 @@ type LocalCacheSupplier struct {
func NewLocalCacheSupplier(metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface) *LocalCacheSupplier {
supplier := &LocalCacheSupplier{
reactionCache: utils.NewLruWithParams(REACTION_CACHE_SIZE, "Reaction", REACTION_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS),
+ roleCache: utils.NewLruWithParams(ROLE_CACHE_SIZE, "Role", ROLE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES),
metrics: metrics,
cluster: cluster,
}
if cluster != nil {
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS, supplier.handleClusterInvalidateReaction)
+ cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES, supplier.handleClusterInvalidateRole)
}
return supplier
diff --git a/store/local_cache_supplier_roles.go b/store/local_cache_supplier_roles.go
new file mode 100644
index 000000000..a9cbda017
--- /dev/null
+++ b/store/local_cache_supplier_roles.go
@@ -0,0 +1,68 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package store
+
+import (
+ "context"
+
+ "github.com/mattermost/mattermost-server/model"
+)
+
+func (s *LocalCacheSupplier) handleClusterInvalidateRole(msg *model.ClusterMessage) {
+ if msg.Data == CLEAR_CACHE_MESSAGE_DATA {
+ s.roleCache.Purge()
+ } else {
+ s.roleCache.Remove(msg.Data)
+ }
+}
+
+func (s *LocalCacheSupplier) RoleSave(ctx context.Context, role *model.Role, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ if len(role.Id) != 0 {
+ defer s.doInvalidateCacheCluster(s.roleCache, role.Name)
+ }
+ return s.Next().RoleSave(ctx, role, hints...)
+}
+
+func (s *LocalCacheSupplier) RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ return s.Next().RoleGet(ctx, roleId, hints...)
+}
+
+func (s *LocalCacheSupplier) RoleGetByName(ctx context.Context, name string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ if result := s.doStandardReadCache(ctx, s.roleCache, name, hints...); result != nil {
+ return result
+ }
+
+ result := s.Next().RoleGetByName(ctx, name, hints...)
+
+ s.doStandardAddToCache(ctx, s.roleCache, name, result, hints...)
+
+ return result
+}
+
+func (s *LocalCacheSupplier) RoleGetByNames(ctx context.Context, roleNames []string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ var foundRoles []*model.Role
+ var rolesToQuery []string
+
+ for _, roleName := range roleNames {
+ if result := s.doStandardReadCache(ctx, s.roleCache, roleName, hints...); result != nil {
+ foundRoles = append(foundRoles, result.Data.(*model.Role))
+ } else {
+ rolesToQuery = append(rolesToQuery, roleName)
+ }
+ }
+
+ result := s.Next().RoleGetByNames(ctx, rolesToQuery, hints...)
+
+ if result.Data != nil {
+ rolesFound := result.Data.([]*model.Role)
+ for _, role := range rolesFound {
+ res := NewSupplierResult()
+ res.Data = role
+ s.doStandardAddToCache(ctx, s.roleCache, role.Name, res, hints...)
+ }
+ result.Data = append(foundRoles, result.Data.([]*model.Role)...)
+ }
+
+ return result
+}
diff --git a/store/redis_supplier.go b/store/redis_supplier.go
index 32dc12033..b8ec794cf 100644
--- a/store/redis_supplier.go
+++ b/store/redis_supplier.go
@@ -132,3 +132,23 @@ func (s *RedisSupplier) ReactionPermanentDeleteBatch(ctx context.Context, endTim
// Ignoring this. It's probably OK to have the emoji slowly expire from Redis.
return s.Next().ReactionPermanentDeleteBatch(ctx, endTime, limit, hints...)
}
+
+func (s *RedisSupplier) RoleSave(ctx context.Context, role *model.Role, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ // TODO: Redis Caching.
+ return s.Next().RoleSave(ctx, role, hints...)
+}
+
+func (s *RedisSupplier) RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ // TODO: Redis Caching.
+ return s.Next().RoleGet(ctx, roleId, hints...)
+}
+
+func (s *RedisSupplier) RoleGetByName(ctx context.Context, name string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ // TODO: Redis Caching.
+ return s.Next().RoleGetByName(ctx, name, hints...)
+}
+
+func (s *RedisSupplier) RoleGetByNames(ctx context.Context, roleNames []string, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
+ // TODO: Redis Caching.
+ return s.Next().RoleGetByNames(ctx, roleNames, hints...)
+}
diff --git a/store/sqlstore/role_store_test.go b/store/sqlstore/role_store_test.go
new file mode 100644
index 000000000..e89930f71
--- /dev/null
+++ b/store/sqlstore/role_store_test.go
@@ -0,0 +1,14 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package sqlstore
+
+import (
+ "testing"
+
+ "github.com/mattermost/mattermost-server/store/storetest"
+)
+
+func TestRoleStore(t *testing.T) {
+ StoreTest(t, storetest.TestRoleStore)
+}
diff --git a/store/sqlstore/role_supplier.go b/store/sqlstore/role_supplier.go
new file mode 100644
index 000000000..41eed85e0
--- /dev/null
+++ b/store/sqlstore/role_supplier.go
@@ -0,0 +1,163 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package sqlstore
+
+import (
+ "context"
+ "database/sql"
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/mattermost/mattermost-server/model"
+ "github.com/mattermost/mattermost-server/store"
+)
+
+type Role struct {
+ Id string
+ Name string
+ DisplayName string
+ Description string
+ Permissions string
+ SchemeManaged bool
+}
+
+func NewRoleFromModel(role *model.Role) *Role {
+ permissionsMap := make(map[string]bool)
+ permissions := ""
+
+ for _, permission := range role.Permissions {
+ if !permissionsMap[permission] {
+ permissions += fmt.Sprintf(" %v", permission)
+ permissionsMap[permission] = true
+ }
+ }
+
+ return &Role{
+ Id: role.Id,
+ Name: role.Name,
+ DisplayName: role.DisplayName,
+ Description: role.Description,
+ Permissions: permissions,
+ SchemeManaged: role.SchemeManaged,
+ }
+}
+
+func (role Role) ToModel() *model.Role {
+ return &model.Role{
+ Id: role.Id,
+ Name: role.Name,
+ DisplayName: role.DisplayName,
+ Description: role.Description,
+ Permissions: strings.Fields(role.Permissions),
+ SchemeManaged: role.SchemeManaged,
+ }
+}
+
+func initSqlSupplierRoles(sqlStore SqlStore) {
+ for _, db := range sqlStore.GetAllConns() {
+ table := db.AddTableWithName(Role{}, "Roles").SetKeys(false, "Id")
+ table.ColMap("Name").SetMaxSize(64).SetUnique(true)
+ table.ColMap("DisplayName").SetMaxSize(128)
+ table.ColMap("Description").SetMaxSize(1024)
+ table.ColMap("Permissions").SetMaxSize(4096)
+ }
+}
+
+func (s *SqlSupplier) RoleSave(ctx context.Context, role *model.Role, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ result := store.NewSupplierResult()
+
+ // Check the role is valid before proceeding.
+ if !role.IsValidWithoutId() {
+ result.Err = model.NewAppError("SqlRoleStore.Save", "store.sql_role.save.invalid_role.app_error", nil, "", http.StatusBadRequest)
+ return result
+ }
+
+ dbRole := NewRoleFromModel(role)
+ if len(dbRole.Id) == 0 {
+ dbRole.Id = model.NewId()
+ if err := s.GetMaster().Insert(dbRole); err != nil {
+ result.Err = model.NewAppError("SqlRoleStore.Save", "store.sql_role.save.insert.app_error", nil, err.Error(), http.StatusInternalServerError)
+ }
+ } else {
+ if rowsChanged, err := s.GetMaster().Update(dbRole); err != nil {
+ result.Err = model.NewAppError("SqlRoleStore.Save", "store.sql_role.save.update.app_error", nil, err.Error(), http.StatusInternalServerError)
+ } else if rowsChanged != 1 {
+ result.Err = model.NewAppError("SqlRoleStore.Save", "store.sql_role.save.update.app_error", nil, "no record to update", http.StatusInternalServerError)
+ }
+ }
+
+ result.Data = dbRole.ToModel()
+
+ return result
+}
+
+func (s *SqlSupplier) RoleGet(ctx context.Context, roleId string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ result := store.NewSupplierResult()
+
+ var dbRole Role
+
+ if err := s.GetReplica().SelectOne(&dbRole, "SELECT * from Roles WHERE Id = :Id", map[string]interface{}{"Id": roleId}); err != nil {
+ if err == sql.ErrNoRows {
+ result.Err = model.NewAppError("SqlRoleStore.Get", "store.sql_role.get.app_error", nil, "Id="+roleId+", "+err.Error(), http.StatusNotFound)
+ } else {
+ result.Err = model.NewAppError("SqlRoleStore.Get", "store.sql_role.get.app_error", nil, err.Error(), http.StatusInternalServerError)
+ }
+ }
+
+ result.Data = dbRole.ToModel()
+
+ return result
+}
+
+func (s *SqlSupplier) RoleGetByName(ctx context.Context, name string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ result := store.NewSupplierResult()
+
+ var dbRole Role
+
+ if err := s.GetReplica().SelectOne(&dbRole, "SELECT * from Roles WHERE Name = :Name", map[string]interface{}{"Name": name}); err != nil {
+ if err == sql.ErrNoRows {
+ result.Err = model.NewAppError("SqlRoleStore.GetByName", "store.sql_role.get_by_name.app_error", nil, "name="+name+",err="+err.Error(), http.StatusNotFound)
+ } else {
+ result.Err = model.NewAppError("SqlRoleStore.GetByName", "store.sql_role.get_by_name.app_error", nil, "name="+name+",err="+err.Error(), http.StatusInternalServerError)
+ }
+ }
+
+ result.Data = dbRole.ToModel()
+
+ return result
+}
+
+func (s *SqlSupplier) RoleGetByNames(ctx context.Context, names []string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ result := store.NewSupplierResult()
+
+ var dbRoles []*Role
+
+ if len(names) == 0 {
+ result.Data = []*model.Role{}
+ return result
+ }
+
+ var searchPlaceholders []string
+ var parameters = map[string]interface{}{}
+ for i, value := range names {
+ searchPlaceholders = append(searchPlaceholders, fmt.Sprintf(":Name%d", i))
+ parameters[fmt.Sprintf("Name%d", i)] = value
+ }
+
+ searchTerm := "Name IN (" + strings.Join(searchPlaceholders, ", ") + ")"
+
+ if _, err := s.GetReplica().Select(&dbRoles, "SELECT * from Roles WHERE "+searchTerm, parameters); err != nil {
+ result.Err = model.NewAppError("SqlRoleStore.GetByNames", "store.sql_role.get_by_names.app_error", nil, err.Error(), http.StatusInternalServerError)
+ }
+
+ var roles []*model.Role
+ for _, dbRole := range dbRoles {
+ roles = append(roles, dbRole.ToModel())
+ }
+
+ result.Data = roles
+
+ return result
+}
diff --git a/store/sqlstore/store.go b/store/sqlstore/store.go
index cfdd7a552..1c623f0b1 100644
--- a/store/sqlstore/store.go
+++ b/store/sqlstore/store.go
@@ -87,4 +87,5 @@ type SqlStore interface {
Job() store.JobStore
Plugin() store.PluginStore
UserAccessToken() store.UserAccessTokenStore
+ Role() store.RoleStore
}
diff --git a/store/sqlstore/supplier.go b/store/sqlstore/supplier.go
index 3b9528578..5e43ee0f0 100644
--- a/store/sqlstore/supplier.go
+++ b/store/sqlstore/supplier.go
@@ -86,6 +86,7 @@ type SqlSupplierOldStores struct {
userAccessToken store.UserAccessTokenStore
plugin store.PluginStore
channelMemberHistory store.ChannelMemberHistoryStore
+ role store.RoleStore
}
type SqlSupplier struct {
@@ -135,6 +136,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
supplier.oldStores.plugin = NewSqlPluginStore(supplier)
initSqlSupplierReactions(supplier)
+ initSqlSupplierRoles(supplier)
err := supplier.GetMaster().CreateTablesIfNotExists()
if err != nil {
@@ -811,6 +813,10 @@ func (ss *SqlSupplier) Plugin() store.PluginStore {
return ss.oldStores.plugin
}
+func (ss *SqlSupplier) Role() store.RoleStore {
+ return ss.oldStores.role
+}
+
func (ss *SqlSupplier) DropAllTables() {
ss.master.TruncateTables()
}
diff --git a/store/store.go b/store/store.go
index 2742c0889..40fd1e23b 100644
--- a/store/store.go
+++ b/store/store.go
@@ -61,6 +61,7 @@ type Store interface {
Status() StatusStore
FileInfo() FileInfoStore
Reaction() ReactionStore
+ Role() RoleStore
Job() JobStore
UserAccessToken() UserAccessTokenStore
ChannelMemberHistory() ChannelMemberHistoryStore
@@ -461,3 +462,10 @@ type PluginStore interface {
Get(pluginId, key string) StoreChannel
Delete(pluginId, key string) StoreChannel
}
+
+type RoleStore interface {
+ Save(role *model.Role) StoreChannel
+ Get(roleId string) StoreChannel
+ GetByName(name string) StoreChannel
+ GetByNames(names []string) StoreChannel
+}
diff --git a/store/storetest/mocks/LayeredStoreDatabaseLayer.go b/store/storetest/mocks/LayeredStoreDatabaseLayer.go
index 9c66c4aac..d0162a01e 100644
--- a/store/storetest/mocks/LayeredStoreDatabaseLayer.go
+++ b/store/storetest/mocks/LayeredStoreDatabaseLayer.go
@@ -416,6 +416,114 @@ func (_m *LayeredStoreDatabaseLayer) ReactionSave(ctx context.Context, reaction
return r0
}
+// Role provides a mock function with given fields:
+func (_m *LayeredStoreDatabaseLayer) Role() store.RoleStore {
+ ret := _m.Called()
+
+ var r0 store.RoleStore
+ if rf, ok := ret.Get(0).(func() store.RoleStore); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.RoleStore)
+ }
+ }
+
+ return r0
+}
+
+// RoleGet provides a mock function with given fields: ctx, roleId, hints
+func (_m *LayeredStoreDatabaseLayer) RoleGet(ctx context.Context, roleId string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, roleId)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, roleId, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
+// RoleGetByName provides a mock function with given fields: ctx, name, hints
+func (_m *LayeredStoreDatabaseLayer) RoleGetByName(ctx context.Context, name string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, name)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, name, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
+// RoleGetByNames provides a mock function with given fields: ctx, names, hints
+func (_m *LayeredStoreDatabaseLayer) RoleGetByNames(ctx context.Context, names []string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, names)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, []string, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, names, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
+// RoleSave provides a mock function with given fields: ctx, role, hints
+func (_m *LayeredStoreDatabaseLayer) RoleSave(ctx context.Context, role *model.Role, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, role)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, *model.Role, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, role, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
// Session provides a mock function with given fields:
func (_m *LayeredStoreDatabaseLayer) Session() store.SessionStore {
ret := _m.Called()
diff --git a/store/storetest/mocks/LayeredStoreSupplier.go b/store/storetest/mocks/LayeredStoreSupplier.go
index f4187dae9..59fd31cb8 100644
--- a/store/storetest/mocks/LayeredStoreSupplier.go
+++ b/store/storetest/mocks/LayeredStoreSupplier.go
@@ -145,6 +145,98 @@ func (_m *LayeredStoreSupplier) ReactionSave(ctx context.Context, reaction *mode
return r0
}
+// RoleGet provides a mock function with given fields: ctx, roleId, hints
+func (_m *LayeredStoreSupplier) RoleGet(ctx context.Context, roleId string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, roleId)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, roleId, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
+// RoleGetByName provides a mock function with given fields: ctx, name, hints
+func (_m *LayeredStoreSupplier) RoleGetByName(ctx context.Context, name string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, name)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, name, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
+// RoleGetByNames provides a mock function with given fields: ctx, names, hints
+func (_m *LayeredStoreSupplier) RoleGetByNames(ctx context.Context, names []string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, names)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, []string, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, names, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
+// RoleSave provides a mock function with given fields: ctx, role, hints
+func (_m *LayeredStoreSupplier) RoleSave(ctx context.Context, role *model.Role, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
+ _va := make([]interface{}, len(hints))
+ for _i := range hints {
+ _va[_i] = hints[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, role)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ var r0 *store.LayeredStoreSupplierResult
+ if rf, ok := ret.Get(0).(func(context.Context, *model.Role, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
+ r0 = rf(ctx, role, hints...)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
+ }
+ }
+
+ return r0
+}
+
// SetChainNext provides a mock function with given fields: _a0
func (_m *LayeredStoreSupplier) SetChainNext(_a0 store.LayeredStoreSupplier) {
_m.Called(_a0)
diff --git a/store/storetest/mocks/RoleStore.go b/store/storetest/mocks/RoleStore.go
new file mode 100644
index 000000000..8150460ae
--- /dev/null
+++ b/store/storetest/mocks/RoleStore.go
@@ -0,0 +1,78 @@
+// Code generated by mockery v1.0.0
+
+// Regenerate this file using `make store-mocks`.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+import model "github.com/mattermost/mattermost-server/model"
+import store "github.com/mattermost/mattermost-server/store"
+
+// RoleStore is an autogenerated mock type for the RoleStore type
+type RoleStore struct {
+ mock.Mock
+}
+
+// Get provides a mock function with given fields: roleId
+func (_m *RoleStore) Get(roleId string) store.StoreChannel {
+ ret := _m.Called(roleId)
+
+ var r0 store.StoreChannel
+ if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
+ r0 = rf(roleId)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.StoreChannel)
+ }
+ }
+
+ return r0
+}
+
+// GetByName provides a mock function with given fields: name
+func (_m *RoleStore) GetByName(name string) store.StoreChannel {
+ ret := _m.Called(name)
+
+ var r0 store.StoreChannel
+ if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
+ r0 = rf(name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.StoreChannel)
+ }
+ }
+
+ return r0
+}
+
+// GetByNames provides a mock function with given fields: names
+func (_m *RoleStore) GetByNames(names []string) store.StoreChannel {
+ ret := _m.Called(names)
+
+ var r0 store.StoreChannel
+ if rf, ok := ret.Get(0).(func([]string) store.StoreChannel); ok {
+ r0 = rf(names)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.StoreChannel)
+ }
+ }
+
+ return r0
+}
+
+// Save provides a mock function with given fields: role
+func (_m *RoleStore) Save(role *model.Role) store.StoreChannel {
+ ret := _m.Called(role)
+
+ var r0 store.StoreChannel
+ if rf, ok := ret.Get(0).(func(*model.Role) store.StoreChannel); ok {
+ r0 = rf(role)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.StoreChannel)
+ }
+ }
+
+ return r0
+}
diff --git a/store/storetest/mocks/SqlStore.go b/store/storetest/mocks/SqlStore.go
index b9b962101..43709fc0e 100644
--- a/store/storetest/mocks/SqlStore.go
+++ b/store/storetest/mocks/SqlStore.go
@@ -538,6 +538,22 @@ func (_m *SqlStore) RenameColumnIfExists(tableName string, oldColumnName string,
return r0
}
+// Role provides a mock function with given fields:
+func (_m *SqlStore) Role() store.RoleStore {
+ ret := _m.Called()
+
+ var r0 store.RoleStore
+ if rf, ok := ret.Get(0).(func() store.RoleStore); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.RoleStore)
+ }
+ }
+
+ return r0
+}
+
// Session provides a mock function with given fields:
func (_m *SqlStore) Session() store.SessionStore {
ret := _m.Called()
diff --git a/store/storetest/mocks/Store.go b/store/storetest/mocks/Store.go
index 40b50a554..cb7e511f6 100644
--- a/store/storetest/mocks/Store.go
+++ b/store/storetest/mocks/Store.go
@@ -283,6 +283,22 @@ func (_m *Store) Reaction() store.ReactionStore {
return r0
}
+// Role provides a mock function with given fields:
+func (_m *Store) Role() store.RoleStore {
+ ret := _m.Called()
+
+ var r0 store.RoleStore
+ if rf, ok := ret.Get(0).(func() store.RoleStore); ok {
+ r0 = rf()
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(store.RoleStore)
+ }
+ }
+
+ return r0
+}
+
// Session provides a mock function with given fields:
func (_m *Store) Session() store.SessionStore {
ret := _m.Called()
diff --git a/store/storetest/role_store.go b/store/storetest/role_store.go
new file mode 100644
index 000000000..499e36e1e
--- /dev/null
+++ b/store/storetest/role_store.go
@@ -0,0 +1,244 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package storetest
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/mattermost/mattermost-server/model"
+ "github.com/mattermost/mattermost-server/store"
+)
+
+func TestRoleStore(t *testing.T, ss store.Store) {
+ t.Run("Save", func(t *testing.T) { testRoleStoreSave(t, ss) })
+ t.Run("Get", func(t *testing.T) { testRoleStoreGet(t, ss) })
+ t.Run("GetByName", func(t *testing.T) { testRoleStoreGetByName(t, ss) })
+ t.Run("GetNames", func(t *testing.T) { testRoleStoreGetByNames(t, ss) })
+}
+
+func testRoleStoreSave(t *testing.T, ss store.Store) {
+ // Save a new role.
+ r1 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "invite_user",
+ "create_public_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+
+ res1 := <-ss.Role().Save(r1)
+ assert.Nil(t, res1.Err)
+ d1 := res1.Data.(*model.Role)
+ assert.Len(t, d1.Id, 26)
+ assert.Equal(t, r1.Name, d1.Name)
+ assert.Equal(t, r1.DisplayName, d1.DisplayName)
+ assert.Equal(t, r1.Description, d1.Description)
+ assert.Equal(t, r1.Permissions, d1.Permissions)
+ assert.Equal(t, r1.SchemeManaged, d1.SchemeManaged)
+
+ // Change the role permissions and update.
+ d1.Permissions = []string{
+ "invite_user",
+ "add_user_to_team",
+ "delete_public_channel",
+ }
+
+ res2 := <-ss.Role().Save(d1)
+ assert.Nil(t, res2.Err)
+ d2 := res2.Data.(*model.Role)
+ assert.Len(t, d2.Id, 26)
+ assert.Equal(t, r1.Name, d2.Name)
+ assert.Equal(t, r1.DisplayName, d2.DisplayName)
+ assert.Equal(t, r1.Description, d2.Description)
+ assert.Equal(t, d1.Permissions, d2.Permissions)
+ assert.Equal(t, r1.SchemeManaged, d2.SchemeManaged)
+
+ // Try saving one with an invalid ID set.
+ r3 := &model.Role{
+ Id: model.NewId(),
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "invite_user",
+ "create_public_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+
+ res3 := <-ss.Role().Save(r3)
+ assert.NotNil(t, res3.Err)
+
+ // Try saving one with a duplicate "name" field.
+ r4 := &model.Role{
+ Name: r1.Name,
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "invite_user",
+ "create_public_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+
+ res4 := <-ss.Role().Save(r4)
+ assert.NotNil(t, res4.Err)
+}
+
+func testRoleStoreGet(t *testing.T, ss store.Store) {
+ // Save a role to test with.
+ r1 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "invite_user",
+ "create_public_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+
+ res1 := <-ss.Role().Save(r1)
+ assert.Nil(t, res1.Err)
+ d1 := res1.Data.(*model.Role)
+ assert.Len(t, d1.Id, 26)
+
+ // Get a valid role
+ res2 := <-ss.Role().Get(d1.Id)
+ assert.Nil(t, res2.Err)
+ d2 := res1.Data.(*model.Role)
+ assert.Equal(t, d1.Id, d2.Id)
+ assert.Equal(t, r1.Name, d2.Name)
+ assert.Equal(t, r1.DisplayName, d2.DisplayName)
+ assert.Equal(t, r1.Description, d2.Description)
+ assert.Equal(t, r1.Permissions, d2.Permissions)
+ assert.Equal(t, r1.SchemeManaged, d2.SchemeManaged)
+
+ // Get an invalid role
+ res3 := <-ss.Role().Get(model.NewId())
+ assert.NotNil(t, res3.Err)
+}
+
+func testRoleStoreGetByName(t *testing.T, ss store.Store) {
+ // Save a role to test with.
+ r1 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "invite_user",
+ "create_public_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+
+ res1 := <-ss.Role().Save(r1)
+ assert.Nil(t, res1.Err)
+ d1 := res1.Data.(*model.Role)
+ assert.Len(t, d1.Id, 26)
+
+ // Get a valid role
+ res2 := <-ss.Role().GetByName(d1.Name)
+ assert.Nil(t, res2.Err)
+ d2 := res1.Data.(*model.Role)
+ assert.Equal(t, d1.Id, d2.Id)
+ assert.Equal(t, r1.Name, d2.Name)
+ assert.Equal(t, r1.DisplayName, d2.DisplayName)
+ assert.Equal(t, r1.Description, d2.Description)
+ assert.Equal(t, r1.Permissions, d2.Permissions)
+ assert.Equal(t, r1.SchemeManaged, d2.SchemeManaged)
+
+ // Get an invalid role
+ res3 := <-ss.Role().GetByName(model.NewId())
+ assert.NotNil(t, res3.Err)
+}
+
+func testRoleStoreGetByNames(t *testing.T, ss store.Store) {
+ // Save some roles to test with.
+ r1 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "invite_user",
+ "create_public_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+ r2 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "read_channel",
+ "create_public_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+ r3 := &model.Role{
+ Name: model.NewId(),
+ DisplayName: model.NewId(),
+ Description: model.NewId(),
+ Permissions: []string{
+ "invite_user",
+ "delete_private_channel",
+ "add_user_to_team",
+ },
+ SchemeManaged: false,
+ }
+
+ res1 := <-ss.Role().Save(r1)
+ assert.Nil(t, res1.Err)
+ d1 := res1.Data.(*model.Role)
+ assert.Len(t, d1.Id, 26)
+
+ res2 := <-ss.Role().Save(r2)
+ assert.Nil(t, res2.Err)
+ d2 := res2.Data.(*model.Role)
+ assert.Len(t, d2.Id, 26)
+
+ res3 := <-ss.Role().Save(r3)
+ assert.Nil(t, res3.Err)
+ d3 := res3.Data.(*model.Role)
+ assert.Len(t, d3.Id, 26)
+
+ // Get two valid roles.
+ n4 := []string{r1.Name, r2.Name}
+ res4 := <-ss.Role().GetByNames(n4)
+ assert.Nil(t, res4.Err)
+ roles4 := res4.Data.([]*model.Role)
+ assert.Len(t, roles4, 2)
+ assert.Contains(t, roles4, d1)
+ assert.Contains(t, roles4, d2)
+ assert.NotContains(t, roles4, d3)
+
+ // Get two invalid roles.
+ n5 := []string{model.NewId(), model.NewId()}
+ res5 := <-ss.Role().GetByNames(n5)
+ assert.Nil(t, res5.Err)
+ roles5 := res5.Data.([]*model.Role)
+ assert.Len(t, roles5, 0)
+
+ // Get one valid one and one invalid one.
+ n6 := []string{r1.Name, model.NewId()}
+ res6 := <-ss.Role().GetByNames(n6)
+ assert.Nil(t, res6.Err)
+ roles6 := res6.Data.([]*model.Role)
+ assert.Len(t, roles6, 1)
+ assert.Contains(t, roles6, d1)
+ assert.NotContains(t, roles6, d2)
+ assert.NotContains(t, roles6, d3)
+}
diff --git a/store/storetest/store.go b/store/storetest/store.go
index 367c5f441..44f426075 100644
--- a/store/storetest/store.go
+++ b/store/storetest/store.go
@@ -43,6 +43,7 @@ type Store struct {
UserAccessTokenStore mocks.UserAccessTokenStore
PluginStore mocks.PluginStore
ChannelMemberHistoryStore mocks.ChannelMemberHistoryStore
+ RoleStore mocks.RoleStore
}
func (s *Store) Team() store.TeamStore { return &s.TeamStore }
@@ -68,6 +69,7 @@ func (s *Store) Reaction() store.ReactionStore { return &s.React
func (s *Store) Job() store.JobStore { return &s.JobStore }
func (s *Store) UserAccessToken() store.UserAccessTokenStore { return &s.UserAccessTokenStore }
func (s *Store) Plugin() store.PluginStore { return &s.PluginStore }
+func (s *Store) Role() store.RoleStore { return &s.RoleStore }
func (s *Store) ChannelMemberHistory() store.ChannelMemberHistoryStore {
return &s.ChannelMemberHistoryStore
}
@@ -104,5 +106,6 @@ func (s *Store) AssertExpectations(t mock.TestingT) bool {
&s.UserAccessTokenStore,
&s.ChannelMemberHistoryStore,
&s.PluginStore,
+ &s.RoleStore,
)
}
diff --git a/utils/authorization.go b/utils/authorization.go
index 39a0d606c..b18ece141 100644
--- a/utils/authorization.go
+++ b/utils/authorization.go
@@ -7,14 +7,7 @@ import (
"github.com/mattermost/mattermost-server/model"
)
-func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
- roles := make(map[string]*model.Role)
- for id, role := range model.DefaultRoles {
- copy := &model.Role{}
- *copy = *role
- roles[id] = copy
- }
-
+func SetRolePermissionsFromConfig(roles map[string]*model.Role, cfg *model.Config) map[string]*model.Role {
if IsLicensed() {
switch *cfg.TeamSettings.RestrictPublicChannelCreation {
case model.PERMISSIONS_ALL:
@@ -222,8 +215,8 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
model.PERMISSION_ADD_USER_TO_TEAM.Id,
)
} else if *cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_ALL {
- roles[model.SYSTEM_USER_ROLE_ID].Permissions = append(
- roles[model.SYSTEM_USER_ROLE_ID].Permissions,
+ roles[model.TEAM_USER_ROLE_ID].Permissions = append(
+ roles[model.TEAM_USER_ROLE_ID].Permissions,
model.PERMISSION_INVITE_USER.Id,
model.PERMISSION_ADD_USER_TO_TEAM.Id,
)
@@ -243,11 +236,6 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
roles[model.CHANNEL_USER_ROLE_ID].Permissions,
model.PERMISSION_DELETE_POST.Id,
)
- roles[model.CHANNEL_ADMIN_ROLE_ID].Permissions = append(
- roles[model.CHANNEL_ADMIN_ROLE_ID].Permissions,
- model.PERMISSION_DELETE_POST.Id,
- model.PERMISSION_DELETE_OTHERS_POSTS.Id,
- )
roles[model.TEAM_ADMIN_ROLE_ID].Permissions = append(
roles[model.TEAM_ADMIN_ROLE_ID].Permissions,
model.PERMISSION_DELETE_POST.Id,
diff --git a/web/web_test.go b/web/web_test.go
index 21a7968b3..f43251143 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -52,6 +52,8 @@ func Setup() *app.App {
URL = fmt.Sprintf("http://localhost:%v", a.Srv.ListenAddr.Port)
ApiClient = model.NewClient(URL)
+ a.DoAdvancedPermissionsMigration()
+
a.Srv.Store.MarkSystemRanUnitTests()
a.UpdateConfig(func(cfg *model.Config) {