summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/admin.go75
-rw-r--r--api/apitestlib.go6
-rw-r--r--api/authorization.go149
-rw-r--r--api/authorization_test.go36
-rw-r--r--api/channel.go145
-rw-r--r--api/channel_test.go27
-rw-r--r--api/cli_test.go4
-rw-r--r--api/command.go48
-rw-r--r--api/context.go92
-rw-r--r--api/context_test.go20
-rw-r--r--api/emoji.go2
-rw-r--r--api/file.go22
-rw-r--r--api/license.go7
-rw-r--r--api/oauth.go54
-rw-r--r--api/oauth_test.go2
-rw-r--r--api/post.go56
-rw-r--r--api/post_test.go1
-rw-r--r--api/team.go62
-rw-r--r--api/team_test.go9
-rw-r--r--api/user.go60
-rw-r--r--api/user_test.go22
-rw-r--r--api/webhook.go111
-rw-r--r--api/webhook_test.go30
-rw-r--r--i18n/en.json24
-rw-r--r--mattermost.go1
-rw-r--r--model/authorization.go371
-rw-r--r--model/channel_member.go11
-rw-r--r--model/channel_member_test.go7
-rw-r--r--model/session.go4
-rw-r--r--model/team_member.go44
-rw-r--r--model/team_member_test.go4
-rw-r--r--model/user.go24
-rw-r--r--model/user_test.go4
-rw-r--r--store/sql_team_store.go2
-rw-r--r--store/sql_upgrade.go16
-rw-r--r--store/sql_user_store.go2
-rw-r--r--store/sql_user_store_test.go2
-rw-r--r--utils/authorization.go81
-rw-r--r--utils/config.go6
-rw-r--r--web/web_test.go4
-rw-r--r--webapp/actions/team_actions.jsx2
-rw-r--r--webapp/components/admin_console/user_item.jsx14
-rw-r--r--webapp/components/team_members_dropdown.jsx14
-rw-r--r--webapp/tests/client_admin.test.jsx22
-rw-r--r--webapp/utils/utils.jsx2
45 files changed, 1099 insertions, 602 deletions
diff --git a/api/admin.go b/api/admin.go
index 573a22c6b..9ac071e6d 100644
--- a/api/admin.go
+++ b/api/admin.go
@@ -25,18 +25,18 @@ import (
func InitAdmin() {
l4g.Debug(utils.T("api.admin.init.debug"))
- BaseRoutes.Admin.Handle("/logs", ApiUserRequired(getLogs)).Methods("GET")
- BaseRoutes.Admin.Handle("/audits", ApiUserRequired(getAllAudits)).Methods("GET")
- BaseRoutes.Admin.Handle("/config", ApiUserRequired(getConfig)).Methods("GET")
- BaseRoutes.Admin.Handle("/save_config", ApiUserRequired(saveConfig)).Methods("POST")
- BaseRoutes.Admin.Handle("/reload_config", ApiUserRequired(reloadConfig)).Methods("GET")
- BaseRoutes.Admin.Handle("/test_email", ApiUserRequired(testEmail)).Methods("POST")
- BaseRoutes.Admin.Handle("/recycle_db_conn", ApiUserRequired(recycleDatabaseConnection)).Methods("GET")
- BaseRoutes.Admin.Handle("/analytics/{id:[A-Za-z0-9]+}/{name:[A-Za-z0-9_]+}", ApiUserRequired(getAnalytics)).Methods("GET")
- BaseRoutes.Admin.Handle("/analytics/{name:[A-Za-z0-9_]+}", ApiUserRequired(getAnalytics)).Methods("GET")
- BaseRoutes.Admin.Handle("/save_compliance_report", ApiUserRequired(saveComplianceReport)).Methods("POST")
- BaseRoutes.Admin.Handle("/compliance_reports", ApiUserRequired(getComplianceReports)).Methods("GET")
- BaseRoutes.Admin.Handle("/download_compliance_report/{id:[A-Za-z0-9]+}", ApiUserRequiredTrustRequester(downloadComplianceReport)).Methods("GET")
+ BaseRoutes.Admin.Handle("/logs", ApiAdminSystemRequired(getLogs)).Methods("GET")
+ BaseRoutes.Admin.Handle("/audits", ApiAdminSystemRequired(getAllAudits)).Methods("GET")
+ BaseRoutes.Admin.Handle("/config", ApiAdminSystemRequired(getConfig)).Methods("GET")
+ BaseRoutes.Admin.Handle("/save_config", ApiAdminSystemRequired(saveConfig)).Methods("POST")
+ BaseRoutes.Admin.Handle("/reload_config", ApiAdminSystemRequired(reloadConfig)).Methods("GET")
+ BaseRoutes.Admin.Handle("/test_email", ApiAdminSystemRequired(testEmail)).Methods("POST")
+ BaseRoutes.Admin.Handle("/recycle_db_conn", ApiAdminSystemRequired(recycleDatabaseConnection)).Methods("GET")
+ BaseRoutes.Admin.Handle("/analytics/{id:[A-Za-z0-9]+}/{name:[A-Za-z0-9_]+}", ApiAdminSystemRequired(getAnalytics)).Methods("GET")
+ BaseRoutes.Admin.Handle("/analytics/{name:[A-Za-z0-9_]+}", ApiAdminSystemRequired(getAnalytics)).Methods("GET")
+ BaseRoutes.Admin.Handle("/save_compliance_report", ApiAdminSystemRequired(saveComplianceReport)).Methods("POST")
+ BaseRoutes.Admin.Handle("/compliance_reports", ApiAdminSystemRequired(getComplianceReports)).Methods("GET")
+ BaseRoutes.Admin.Handle("/download_compliance_report/{id:[A-Za-z0-9]+}", ApiAdminSystemRequiredTrustRequester(downloadComplianceReport)).Methods("GET")
BaseRoutes.Admin.Handle("/upload_brand_image", ApiAdminSystemRequired(uploadBrandImage)).Methods("POST")
BaseRoutes.Admin.Handle("/get_brand_image", ApiAppHandlerTrustRequester(getBrandImage)).Methods("GET")
BaseRoutes.Admin.Handle("/reset_mfa", ApiAdminSystemRequired(adminResetMfa)).Methods("POST")
@@ -52,11 +52,6 @@ func InitAdmin() {
}
func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
-
- if !c.HasSystemAdminPermissions("getLogs") {
- return
- }
-
lines, err := GetLogs()
if err != nil {
c.Err = err
@@ -99,11 +94,6 @@ func GetLogs() ([]string, *model.AppError) {
}
func getClusterStatus(c *Context, w http.ResponseWriter, r *http.Request) {
-
- if !c.HasSystemAdminPermissions("getClusterStatus") {
- return
- }
-
infos := make([]*model.ClusterInfo, 0)
if einterfaces.GetClusterInterface() != nil {
infos = einterfaces.GetClusterInterface().GetClusterInfos()
@@ -113,11 +103,6 @@ func getClusterStatus(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getAllAudits(c *Context, w http.ResponseWriter, r *http.Request) {
-
- if !c.HasSystemAdminPermissions("getAllAudits") {
- return
- }
-
if result := <-Srv.Store.Audit().Get("", 200); result.Err != nil {
c.Err = result.Err
return
@@ -139,10 +124,6 @@ func getAllAudits(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getConfig(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("getConfig") {
- return
- }
-
json := utils.Cfg.ToJson()
cfg := model.ConfigFromJson(strings.NewReader(json))
@@ -153,10 +134,6 @@ func getConfig(c *Context, w http.ResponseWriter, r *http.Request) {
}
func reloadConfig(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("reloadConfig") {
- return
- }
-
utils.LoadConfig(utils.CfgFileName)
// start/restart email batching job if necessary
@@ -167,10 +144,6 @@ func reloadConfig(c *Context, w http.ResponseWriter, r *http.Request) {
}
func saveConfig(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("getConfig") {
- return
- }
-
cfg := model.ConfigFromJson(r.Body)
if cfg == nil {
c.SetInvalidParam("saveConfig", "config")
@@ -219,10 +192,6 @@ func saveConfig(c *Context, w http.ResponseWriter, r *http.Request) {
}
func recycleDatabaseConnection(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("recycleDatabaseConnection") {
- return
- }
-
oldStore := Srv.Store
l4g.Warn(utils.T("api.admin.recycle_db_start.warn"))
@@ -238,10 +207,6 @@ func recycleDatabaseConnection(c *Context, w http.ResponseWriter, r *http.Reques
}
func testEmail(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("testEmail") {
- return
- }
-
cfg := model.ConfigFromJson(r.Body)
if cfg == nil {
c.SetInvalidParam("testEmail", "config")
@@ -282,10 +247,6 @@ func testEmail(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getComplianceReports(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("getComplianceReports") {
- return
- }
-
if !*utils.Cfg.ComplianceSettings.Enable || !utils.IsLicensed || !*utils.License.Features.Compliance {
c.Err = model.NewLocAppError("getComplianceReports", "ent.compliance.licence_disable.app_error", nil, "")
return
@@ -301,10 +262,6 @@ func getComplianceReports(c *Context, w http.ResponseWriter, r *http.Request) {
}
func saveComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("getComplianceReports") {
- return
- }
-
if !*utils.Cfg.ComplianceSettings.Enable || !utils.IsLicensed || !*utils.License.Features.Compliance || einterfaces.GetComplianceInterface() == nil {
c.Err = model.NewLocAppError("saveComplianceReport", "ent.compliance.licence_disable.app_error", nil, "")
return
@@ -331,10 +288,6 @@ func saveComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) {
}
func downloadComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("downloadComplianceReport") {
- return
- }
-
if !*utils.Cfg.ComplianceSettings.Enable || !utils.IsLicensed || !*utils.License.Features.Compliance || einterfaces.GetComplianceInterface() == nil {
c.Err = model.NewLocAppError("downloadComplianceReport", "ent.compliance.licence_disable.app_error", nil, "")
return
@@ -380,10 +333,6 @@ func downloadComplianceReport(c *Context, w http.ResponseWriter, r *http.Request
}
func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasSystemAdminPermissions("getAnalytics") {
- return
- }
-
params := mux.Vars(r)
teamId := params["id"]
name := params["name"]
diff --git a/api/apitestlib.go b/api/apitestlib.go
index ea0de4716..2511513bb 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -91,7 +91,7 @@ func (me *TestHelper) InitSystemAdmin() *TestHelper {
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- UpdateUserRoles(c, me.SystemAdminUser, model.ROLE_SYSTEM_ADMIN)
+ UpdateUserRoles(c, me.SystemAdminUser, model.ROLE_SYSTEM_USER.Id+" "+model.ROLE_SYSTEM_ADMIN.Id)
me.SystemAdminUser.Password = "Password1"
me.LoginSystemAdmin()
me.SystemAdminChannel = me.CreateChannel(me.SystemAdminClient, me.SystemAdminTeam)
@@ -157,13 +157,15 @@ func LinkUserToTeam(user *model.User, team *model.Team) {
func UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
utils.DisableDebugLogForTest()
- tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.ROLE_TEAM_ADMIN}
+ tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id, Roles: model.ROLE_TEAM_USER.Id + " " + model.ROLE_TEAM_ADMIN.Id}
if tmr := <-Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
+ utils.EnableDebugLogForTest()
l4g.Error(tmr.Err.Error())
l4g.Close()
time.Sleep(time.Second)
panic(tmr.Err)
}
+ utils.EnableDebugLogForTest()
}
func (me *TestHelper) CreateChannel(client *model.Client, team *model.Team) *model.Channel {
diff --git a/api/authorization.go b/api/authorization.go
new file mode 100644
index 000000000..fb04b069b
--- /dev/null
+++ b/api/authorization.go
@@ -0,0 +1,149 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api
+
+import (
+ "net/http"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/model"
+)
+
+func HasPermissionToContext(c *Context, permission *model.Permission) bool {
+ userRoles := c.Session.GetUserRoles()
+ if !CheckIfRolesGrantPermission(userRoles, permission.Id) {
+ c.Err = model.NewLocAppError("HasPermissionToContext", "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", teamId="+c.TeamId+" permission="+permission.Id+" "+model.RoleIdsToString(userRoles))
+ c.Err.StatusCode = http.StatusForbidden
+ return false
+ }
+
+ return true
+}
+
+func HasPermissionTo(user *model.User, permission *model.Permission) bool {
+ roles := user.GetRoles()
+
+ return CheckIfRolesGrantPermission(roles, permission.Id)
+}
+
+func HasPermissionToCurrentTeamContext(c *Context, permission *model.Permission) bool {
+ return HasPermissionToTeamContext(c, c.TeamId, permission)
+}
+
+func HasPermissionToTeamContext(c *Context, teamId string, permission *model.Permission) bool {
+ teamMember := c.Session.GetTeamByTeamId(teamId)
+ if teamMember != nil {
+ roles := teamMember.GetRoles()
+
+ if CheckIfRolesGrantPermission(roles, permission.Id) {
+ return true
+ }
+ }
+
+ if HasPermissionToContext(c, permission) {
+ return true
+ }
+
+ c.Err = model.NewLocAppError("HasPermissionToTeamContext", "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", teamId="+c.TeamId+" permission="+permission.Id)
+ c.Err.StatusCode = http.StatusForbidden
+ return false
+}
+
+func HasPermissionToTeam(user *model.User, teamMember *model.TeamMember, permission *model.Permission) bool {
+ if teamMember == nil {
+ return false
+ }
+
+ roles := teamMember.GetRoles()
+
+ if CheckIfRolesGrantPermission(roles, permission.Id) {
+ return true
+ }
+
+ return HasPermissionTo(user, permission)
+}
+
+func HasPermissionToChannelContext(c *Context, channelId string, permission *model.Permission) bool {
+ cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
+
+ var channelRoles []string
+ if cmcresult := <-cmc; cmcresult.Err == nil {
+ channelMember := cmcresult.Data.(model.ChannelMember)
+ channelRoles = channelMember.GetRoles()
+
+ if CheckIfRolesGrantPermission(channelRoles, permission.Id) {
+ return true
+ }
+ }
+
+ cc := Srv.Store.Channel().Get(channelId)
+ if ccresult := <-cc; ccresult.Err == nil {
+ channel := ccresult.Data.(*model.Channel)
+
+ if teamMember := c.Session.GetTeamByTeamId(channel.TeamId); teamMember != nil {
+ roles := teamMember.GetRoles()
+
+ if CheckIfRolesGrantPermission(roles, permission.Id) {
+ return true
+ }
+ }
+
+ }
+
+ if HasPermissionToContext(c, permission) {
+ return true
+ }
+
+ c.Err = model.NewLocAppError("HasPermissionToChannelContext", "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", "+"permission="+permission.Id+" channelRoles="+model.RoleIdsToString(channelRoles))
+ c.Err.StatusCode = http.StatusForbidden
+ return false
+}
+
+func HasPermissionToChannel(user *model.User, teamMember *model.TeamMember, channelMember *model.ChannelMember, permission *model.Permission) bool {
+ if channelMember == nil {
+ return false
+ }
+
+ roles := channelMember.GetRoles()
+
+ if CheckIfRolesGrantPermission(roles, permission.Id) {
+ return true
+ }
+
+ return HasPermissionToTeam(user, teamMember, permission)
+}
+
+func HasPermissionToUser(c *Context, userId string) bool {
+ // You are the user (users autmaticly have permissions to themselves)
+ if c.Session.UserId == userId {
+ return true
+ }
+
+ // You have permission
+ if HasPermissionToContext(c, model.PERMISSION_EDIT_OTHER_USERS) {
+ return true
+ }
+
+ c.Err = model.NewLocAppError("HasPermissionToUser", "api.context.permissions.app_error", nil, "userId="+userId)
+ c.Err.StatusCode = http.StatusForbidden
+ return false
+}
+
+func CheckIfRolesGrantPermission(roles []string, permissionId string) bool {
+ for _, roleId := range roles {
+ if role, ok := model.BuiltInRoles[roleId]; !ok {
+ l4g.Debug("Bad role in system " + roleId)
+ return false
+ } else {
+ permissions := role.Permissions
+ for _, permission := range permissions {
+ if permission == permissionId {
+ return true
+ }
+ }
+ }
+ }
+
+ return false
+}
diff --git a/api/authorization_test.go b/api/authorization_test.go
new file mode 100644
index 000000000..5613751c2
--- /dev/null
+++ b/api/authorization_test.go
@@ -0,0 +1,36 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/model"
+)
+
+func TestCheckIfRolesGrantPermission(t *testing.T) {
+ Setup()
+
+ cases := []struct {
+ roles []string
+ permissionId string
+ shouldGrant bool
+ }{
+ {[]string{model.ROLE_SYSTEM_ADMIN.Id}, model.ROLE_SYSTEM_ADMIN.Permissions[0], true},
+ {[]string{model.ROLE_SYSTEM_ADMIN.Id}, "non-existant-permission", false},
+ {[]string{model.ROLE_CHANNEL_USER.Id}, model.ROLE_CHANNEL_USER.Permissions[0], true},
+ {[]string{model.ROLE_CHANNEL_USER.Id}, model.PERMISSION_MANAGE_SYSTEM.Id, false},
+ {[]string{model.ROLE_SYSTEM_ADMIN.Id, model.ROLE_CHANNEL_USER.Id}, model.PERMISSION_MANAGE_SYSTEM.Id, true},
+ {[]string{model.ROLE_CHANNEL_USER.Id, model.ROLE_SYSTEM_ADMIN.Id}, model.PERMISSION_MANAGE_SYSTEM.Id, true},
+ {[]string{model.ROLE_TEAM_USER.Id, model.ROLE_TEAM_ADMIN.Id}, model.PERMISSION_MANAGE_SLASH_COMMANDS.Id, true},
+ {[]string{model.ROLE_TEAM_ADMIN.Id, model.ROLE_TEAM_USER.Id}, model.PERMISSION_MANAGE_SLASH_COMMANDS.Id, true},
+ }
+
+ for testnum, testcase := range cases {
+ if CheckIfRolesGrantPermission(testcase.roles, testcase.permissionId) != testcase.shouldGrant {
+ t.Fatal("Failed test case ", testnum)
+ }
+ }
+
+}
diff --git a/api/channel.go b/api/channel.go
index c477a5ee4..734dac744 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -60,22 +60,21 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
channel.TeamId = c.TeamId
}
- if err := CanManageChannel(c, channel); err != nil {
- c.Err = err
+ if channel.Type == model.CHANNEL_DIRECT {
+ c.Err = model.NewLocAppError("createDirectChannel", "api.channel.create_channel.direct_channel.app_error", nil, "")
return
}
- if !c.HasPermissionsToTeam(channel.TeamId, "createChannel") {
+ if strings.Index(channel.Name, "__") > 0 {
+ c.Err = model.NewLocAppError("createDirectChannel", "api.channel.create_channel.invalid_character.app_error", nil, "")
return
}
- if channel.Type == model.CHANNEL_DIRECT {
- c.Err = model.NewLocAppError("createDirectChannel", "api.channel.create_channel.direct_channel.app_error", nil, "")
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToTeamContext(c, channel.TeamId, model.PERMISSION_CREATE_PUBLIC_CHANNEL) {
return
}
- if strings.Index(channel.Name, "__") > 0 {
- c.Err = model.NewLocAppError("createDirectChannel", "api.channel.create_channel.invalid_character.app_error", nil, "")
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToTeamContext(c, channel.TeamId, model.PERMISSION_CREATE_PRIVATE_CHANNEL) {
return
}
@@ -96,8 +95,12 @@ func CreateChannel(c *Context, channel *model.Channel, addMember bool) (*model.C
sc := result.Data.(*model.Channel)
if addMember {
- cm := &model.ChannelMember{ChannelId: sc.Id, UserId: c.Session.UserId,
- Roles: model.CHANNEL_ROLE_ADMIN, NotifyProps: model.GetDefaultChannelNotifyProps()}
+ cm := &model.ChannelMember{
+ ChannelId: sc.Id,
+ UserId: c.Session.UserId,
+ Roles: model.ROLE_CHANNEL_USER.Id + " " + model.ROLE_CHANNEL_ADMIN.Id,
+ NotifyProps: model.GetDefaultChannelNotifyProps(),
+ }
if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
return nil, cmresult.Err
@@ -111,6 +114,9 @@ func CreateChannel(c *Context, channel *model.Channel, addMember bool) (*model.C
}
func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
+ if !HasPermissionToContext(c, model.PERMISSION_CREATE_DIRECT_CHANNEL) {
+ return
+ }
data := model.MapFromJson(r.Body)
@@ -146,10 +152,12 @@ func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *mo
cm1 := &model.ChannelMember{
UserId: userId,
NotifyProps: model.GetDefaultChannelNotifyProps(),
+ Roles: model.ROLE_CHANNEL_USER.Id,
}
cm2 := &model.ChannelMember{
UserId: otherUserId,
NotifyProps: model.GetDefaultChannelNotifyProps(),
+ Roles: model.ROLE_CHANNEL_USER.Id,
}
if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil {
@@ -184,30 +192,16 @@ func CreateDefaultChannels(c *Context, teamId string) ([]*model.Channel, *model.
return channels, nil
}
-func CanManageChannel(c *Context, channel *model.Channel) *model.AppError {
- if utils.IsLicensed {
- if channel.Type == model.CHANNEL_OPEN {
- if *utils.Cfg.TeamSettings.RestrictPublicChannelManagement == model.PERMISSIONS_SYSTEM_ADMIN && !c.IsSystemAdmin() {
- return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.public_restricted_system_admin.app_error", nil, "")
- }
-
- if *utils.Cfg.TeamSettings.RestrictPublicChannelManagement == model.PERMISSIONS_TEAM_ADMIN && !c.IsTeamAdmin() {
- return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.public_restricted_team_admin.app_error", nil, "")
- }
- }
-
- if channel.Type == model.CHANNEL_PRIVATE {
- if *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement == model.PERMISSIONS_SYSTEM_ADMIN && !c.IsSystemAdmin() {
- return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.private_restricted_system_admin.app_error", nil, "")
- }
+func CanManageChannel(c *Context, channel *model.Channel) bool {
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES) {
+ return false
+ }
- if *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement == model.PERMISSIONS_TEAM_ADMIN && !c.IsTeamAdmin() {
- return model.NewLocAppError("CanManageChannel", "api.channel.can_manage_channel.private_restricted_team_admin.app_error", nil, "")
- }
- }
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES) {
+ return false
}
- return nil
+ return true
}
func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -232,12 +226,7 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
oldChannel := cresult.Data.(*model.Channel)
// Don't need to do anything with channel member, just wanted to confirm it exists
- if err := CanManageChannel(c, oldChannel); err != nil {
- c.Err = err
- return
- }
-
- if !c.HasPermissionsToTeam(oldChannel.TeamId, "updateChannel") {
+ if !CanManageChannel(c, channel) {
return
}
@@ -308,14 +297,10 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
channel := cresult.Data.(*model.Channel)
// Don't need to do anything with channel member, just wanted to confirm it exists
- if err := CanManageChannel(c, channel); err != nil {
- c.Err = err
+ if !CanManageChannel(c, channel) {
return
}
- if channel.TeamId != "" && !c.HasPermissionsToTeam(channel.TeamId, "updateChannelHeader") {
- return
- }
oldChannelHeader := channel.Header
channel.Header = channelHeader
@@ -387,12 +372,7 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
channel := cresult.Data.(*model.Channel)
// Don't need to do anything with channel member, just wanted to confirm it exists
- if err := CanManageChannel(c, channel); err != nil {
- c.Err = err
- return
- }
-
- if !c.HasPermissionsToTeam(channel.TeamId, "updateChannelPurpose") {
+ if !CanManageChannel(c, channel) {
return
}
@@ -411,6 +391,7 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
func getChannels(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team
+ // Get's all channels the user is a member of
if result := <-Srv.Store.Channel().GetChannels(c.TeamId, c.Session.UserId); result.Err != nil {
if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
@@ -436,6 +417,9 @@ func getChannels(c *Context, w http.ResponseWriter, r *http.Request) {
func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team
+ if !HasPermissionToTeamContext(c, c.TeamId, model.PERMISSION_LIST_TEAM_CHANNELS) {
+ return
+ }
if result := <-Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId); result.Err != nil {
c.Err = result.Err
@@ -523,7 +507,7 @@ func joinChannel(c *Context, channelChannel store.StoreChannel, userChannel stor
return nil, channel
}
- if !c.HasPermissionsToTeam(channel.TeamId, "join") {
+ if !HasPermissionToTeamContext(c, channel.TeamId, model.PERMISSION_JOIN_PUBLIC_CHANNELS) {
return c.Err, nil
}
@@ -581,7 +565,12 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
return &channelMember, nil
}
- newMember := &model.ChannelMember{ChannelId: channel.Id, UserId: user.Id, NotifyProps: model.GetDefaultChannelNotifyProps()}
+ newMember := &model.ChannelMember{
+ ChannelId: channel.Id,
+ UserId: user.Id,
+ NotifyProps: model.GetDefaultChannelNotifyProps(),
+ Roles: model.ROLE_CHANNEL_USER.Id,
+ }
if result := <-Srv.Store.Channel().SaveMember(newMember); result.Err != nil {
l4g.Error("Failed to add member user_id=%v channel_id=%v err=%v", user.Id, channel.Id, result.Err)
return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "")
@@ -669,10 +658,6 @@ func leave(c *Context, w http.ResponseWriter, r *http.Request) {
user := uresult.Data.(*model.User)
membersCount := ccmresult.Data.(int64)
- if !c.HasPermissionsToTeam(channel.TeamId, "leave") {
- return
- }
-
if channel.Type == model.CHANNEL_DIRECT {
c.Err = model.NewLocAppError("leave", "api.channel.leave.direct.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
@@ -746,14 +731,13 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
// Allow delete if user is the only member left in channel
if memberCount > 1 {
- if err := CanManageChannel(c, channel); err != nil {
- c.Err = err
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToTeamContext(c, channel.TeamId, model.PERMISSION_DELETE_PUBLIC_CHANNEL) {
return
}
- }
- if !c.HasPermissionsToTeam(channel.TeamId, "deleteChannel") {
- return
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToTeamContext(c, channel.TeamId, model.PERMISSION_DELETE_PRIVATE_CHANNEL) {
+ return
+ }
}
if channel.DeleteAt > 0 {
@@ -901,7 +885,6 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- //pchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
cchan := Srv.Store.Channel().Get(id)
cmchan := Srv.Store.Channel().GetMember(id, c.Session.UserId)
@@ -974,24 +957,20 @@ func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = ccmresult.Err
return
} else {
- member := cmresult.Data.(model.ChannelMember)
+ //member := cmresult.Data.(model.ChannelMember)
extraMembers := ecmresult.Data.([]model.ExtraMember)
memberCount := ccmresult.Data.(int64)
- if len(channel.TeamId) > 0 && !c.HasPermissionsToTeam(channel.TeamId, "getChannelExtraInfo") {
- return
- }
-
- if !c.HasPermissionsToUser(member.UserId, "getChannelExtraInfo") {
- return
- }
-
if channel.DeleteAt > 0 {
c.Err = model.NewLocAppError("getChannelExtraInfo", "api.channel.get_channel_extra_info.deleted.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
+ if !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) {
+ return
+ }
+
data := model.ChannelExtra{Id: channel.Id, Members: extraMembers, MemberCount: memberCount}
w.Header().Set(model.HEADER_ETAG_SERVER, extraEtag)
w.Write([]byte(data.ToJson()))
@@ -1010,16 +989,9 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
sc := Srv.Store.Channel().Get(id)
ouc := Srv.Store.User().Get(c.Session.UserId)
nuc := Srv.Store.User().Get(userId)
-
- // Only need to be a member of the channel to add a new member
- if !c.HasPermissionsToChannel(cchan, "addMember") {
- return
- }
-
if nresult := <-nuc; nresult.Err != nil {
c.Err = model.NewLocAppError("addMember", "api.channel.add_member.find_user.app_error", nil, "")
return
@@ -1030,6 +1002,14 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
channel := cresult.Data.(*model.Channel)
nUser := nresult.Data.(*model.User)
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
+ return
+ }
+
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
+ return
+ }
+
if oresult := <-ouc; oresult.Err != nil {
c.Err = model.NewLocAppError("addMember", "api.channel.add_member.user_adding.app_error", nil, "")
return
@@ -1082,15 +1062,12 @@ func removeMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
channel := cresult.Data.(*model.Channel)
- removerChannelMember := cmcresult.Data.(model.ChannelMember)
- if !c.HasPermissionsToTeam(channel.TeamId, "removeMember") {
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
return
}
- if !strings.Contains(removerChannelMember.Roles, model.CHANNEL_ROLE_ADMIN) && !c.IsTeamAdmin() {
- c.Err = model.NewLocAppError("updateChannel", "api.channel.remove_member.permissions.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
return
}
@@ -1145,13 +1122,7 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
-
- if !c.HasPermissionsToUser(userId, "updateNotifyLevel") {
- return
- }
-
- if !c.HasPermissionsToChannel(cchan, "updateNotifyLevel") {
+ if !HasPermissionToUser(c, userId) {
return
}
diff --git a/api/channel_test.go b/api/channel_test.go
index 7046a9868..a3f3e211c 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -4,13 +4,14 @@
package api
import (
- "github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
- "github.com/mattermost/platform/utils"
"net/http"
"strings"
"testing"
"time"
+
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
)
func TestCreateChannel(t *testing.T) {
@@ -100,9 +101,11 @@ func TestCreateChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel
utils.IsLicensed = isLicensed
+ utils.SetDefaultRolesBasedOnConfig()
}()
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
+ utils.SetDefaultRolesBasedOnConfig()
utils.IsLicensed = true
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
@@ -116,6 +119,7 @@ func TestCreateChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
channel2.Name = "a" + model.NewId() + "a"
channel3.Name = "a" + model.NewId() + "a"
@@ -140,6 +144,7 @@ func TestCreateChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
channel2.Name = "a" + model.NewId() + "a"
channel3.Name = "a" + model.NewId() + "a"
@@ -286,10 +291,12 @@ func TestUpdateChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel
utils.IsLicensed = isLicensed
+ utils.SetDefaultRolesBasedOnConfig()
}()
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
utils.IsLicensed = true
+ utils.SetDefaultRolesBasedOnConfig()
channel2 := th.CreateChannel(Client, team)
channel3 := th.CreatePrivateChannel(Client, team)
@@ -310,6 +317,7 @@ func TestUpdateChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.UpdateChannel(channel2); err == nil {
t.Fatal("should have errored not team admin")
@@ -332,6 +340,7 @@ func TestUpdateChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.UpdateChannel(channel2); err == nil {
t.Fatal("should have errored not system admin")
@@ -419,10 +428,12 @@ func TestUpdateChannelHeader(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel
utils.IsLicensed = isLicensed
+ utils.SetDefaultRolesBasedOnConfig()
}()
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
utils.IsLicensed = true
+ utils.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
channel2 := th.CreateChannel(Client, team)
@@ -447,6 +458,7 @@ func TestUpdateChannelHeader(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.UpdateChannelHeader(data2); err == nil {
t.Fatal("should have errored not team admin")
@@ -469,6 +481,7 @@ func TestUpdateChannelHeader(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.UpdateChannelHeader(data2); err == nil {
t.Fatal("should have errored not system admin")
@@ -545,10 +558,12 @@ func TestUpdateChannelPurpose(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel
utils.IsLicensed = isLicensed
+ utils.SetDefaultRolesBasedOnConfig()
}()
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
utils.IsLicensed = true
+ utils.SetDefaultRolesBasedOnConfig()
th.LoginBasic()
channel2 := th.CreateChannel(Client, team)
@@ -573,6 +588,7 @@ func TestUpdateChannelPurpose(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.UpdateChannelPurpose(data2); err == nil {
t.Fatal("should have errored not team admin")
@@ -595,6 +611,7 @@ func TestUpdateChannelPurpose(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.UpdateChannelPurpose(data2); err == nil {
t.Fatal("should have errored not system admin")
@@ -986,10 +1003,12 @@ func TestDeleteChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel
utils.IsLicensed = isLicensed
+ utils.SetDefaultRolesBasedOnConfig()
}()
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL
utils.IsLicensed = true
+ utils.SetDefaultRolesBasedOnConfig()
th.LoginSystemAdmin()
LinkUserToTeam(th.BasicUser, team)
@@ -1013,6 +1032,7 @@ func TestDeleteChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_TEAM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_TEAM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
th.LoginSystemAdmin()
@@ -1044,6 +1064,7 @@ func TestDeleteChannel(t *testing.T) {
*utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
*utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_SYSTEM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
th.LoginSystemAdmin()
diff --git a/api/cli_test.go b/api/cli_test.go
index 65afc81e9..c25394c17 100644
--- a/api/cli_test.go
+++ b/api/cli_test.go
@@ -118,7 +118,7 @@ func TestCliAssignRole(t *testing.T) {
th := Setup().InitBasic()
- cmd := exec.Command("bash", "-c", `go run ../mattermost.go -assign_role -email="`+th.BasicUser.Email+`" -role="system_admin"`)
+ cmd := exec.Command("bash", "-c", `go run ../mattermost.go -assign_role -email="`+th.BasicUser.Email+`" -role="system_user system_admin"`)
output, err := cmd.CombinedOutput()
if err != nil {
t.Log(string(output))
@@ -129,7 +129,7 @@ func TestCliAssignRole(t *testing.T) {
t.Fatal()
} else {
user := result.Data.(*model.User)
- if user.Roles != "system_admin" {
+ if user.Roles != "system_user system_admin" {
t.Fatal()
}
}
diff --git a/api/command.go b/api/command.go
index 5556ed817..5cf9d730b 100644
--- a/api/command.go
+++ b/api/command.go
@@ -97,9 +97,7 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
}
if len(channelId) > 0 {
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
-
- if !c.HasPermissionsToChannel(cchan, "checkCommand") {
+ if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_USE_SLASH_COMMANDS) {
return
}
}
@@ -272,12 +270,10 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("createCommand", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
+ c.Err = model.NewLocAppError("createCommand", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -330,12 +326,10 @@ func listTeamCommands(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("listTeamCommands", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
+ c.Err = model.NewLocAppError("listTeamCommands", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
if result := <-Srv.Store.Command().GetByTeam(c.TeamId); result.Err != nil {
@@ -354,12 +348,10 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("regenCommandToken", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
+ c.Err = model.NewLocAppError("regenCommandToken", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -379,7 +371,7 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
cmd = result.Data.(*model.Command)
- if c.TeamId != cmd.TeamId || (c.Session.UserId != cmd.CreatorId && !c.IsTeamAdmin()) {
+ if c.TeamId != cmd.TeamId || (c.Session.UserId != cmd.CreatorId && !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS)) {
c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("regenToken", "api.command.regen.app_error", nil, "user_id="+c.Session.UserId)
return
@@ -403,12 +395,10 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("deleteCommand", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
+ c.Err = model.NewLocAppError("deleteCommand", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -425,7 +415,7 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = result.Err
return
} else {
- if c.TeamId != result.Data.(*model.Command).TeamId || (c.Session.UserId != result.Data.(*model.Command).CreatorId && !c.IsTeamAdmin()) {
+ if c.TeamId != result.Data.(*model.Command).TeamId || (c.Session.UserId != result.Data.(*model.Command).CreatorId && HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS)) {
c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("deleteCommand", "api.command.delete.app_error", nil, "user_id="+c.Session.UserId)
return
diff --git a/api/context.go b/api/context.go
index b63005d64..81a2c021d 100644
--- a/api/context.go
+++ b/api/context.go
@@ -16,7 +16,6 @@ import (
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
@@ -77,6 +76,10 @@ func ApiAdminSystemRequired(h func(*Context, http.ResponseWriter, *http.Request)
return &handler{h, true, true, true, false, false, false}
}
+func ApiAdminSystemRequiredTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
+ return &handler{h, true, true, true, false, false, true}
+}
+
func ApiAppHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, false, false, true, false, false, true}
}
@@ -202,10 +205,6 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c.SystemAdminRequired()
}
- if c.Err == nil && len(c.TeamId) > 0 && !h.isTeamIndependent {
- c.HasPermissionsToTeam(c.TeamId, "TeamRoute")
- }
-
if c.Err == nil && h.isUserActivity && token != "" && len(c.Session.UserId) > 0 {
SetStatusOnline(c.Session.UserId, c.Session.Id, false)
}
@@ -320,90 +319,13 @@ func (c *Context) SystemAdminRequired() {
c.Err = model.NewLocAppError("", "api.context.session_expired.app_error", nil, "SystemAdminRequired")
c.Err.StatusCode = http.StatusUnauthorized
return
- } else if !c.IsSystemAdmin() {
+ } else if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
c.Err = model.NewLocAppError("", "api.context.permissions.app_error", nil, "AdminRequired")
c.Err.StatusCode = http.StatusForbidden
return
}
}
-func (c *Context) HasPermissionsToUser(userId string, where string) bool {
-
- // You are the user
- if c.Session.UserId == userId {
- return true
- }
-
- // You're a mattermost system admin and you're on the VPN
- if c.IsSystemAdmin() {
- return true
- }
-
- c.Err = model.NewLocAppError(where, "api.context.permissions.app_error", nil, "userId="+userId)
- c.Err.StatusCode = http.StatusForbidden
- return false
-}
-
-func (c *Context) HasPermissionsToTeam(teamId string, where string) bool {
- if c.IsSystemAdmin() {
- return true
- }
-
- for _, teamMember := range c.Session.TeamMembers {
- if teamId == teamMember.TeamId {
- return true
- }
- }
-
- c.Err = model.NewLocAppError(where, "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", teamId="+teamId)
- c.Err.StatusCode = http.StatusForbidden
- return false
-}
-
-func (c *Context) HasPermissionsToChannel(sc store.StoreChannel, where string) bool {
- if cresult := <-sc; cresult.Err != nil {
- c.Err = cresult.Err
- return false
- } else if cresult.Data.(int64) != 1 {
- c.Err = model.NewLocAppError(where, "api.context.permissions.app_error", nil, "userId="+c.Session.UserId)
- c.Err.StatusCode = http.StatusForbidden
- return false
- }
-
- return true
-}
-
-func (c *Context) HasSystemAdminPermissions(where string) bool {
- if c.IsSystemAdmin() {
- return true
- }
-
- c.Err = model.NewLocAppError(where, "api.context.system_permissions.app_error", nil, "userId="+c.Session.UserId)
- c.Err.StatusCode = http.StatusForbidden
- return false
-}
-
-func (c *Context) IsSystemAdmin() bool {
- if model.IsInRole(c.Session.Roles, model.ROLE_SYSTEM_ADMIN) {
- return true
- }
- return false
-}
-
-func (c *Context) IsTeamAdmin() bool {
-
- if c.IsSystemAdmin() {
- return true
- }
-
- teamMember := c.Session.GetTeamByTeamId(c.TeamId)
- if teamMember == nil {
- return false
- }
-
- return teamMember.IsTeamAdmin()
-}
-
func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) {
cookie := &http.Cookie{
Name: model.SESSION_COOKIE_TOKEN,
@@ -463,6 +385,10 @@ func (c *Context) GetSiteURL() string {
return c.siteURL
}
+func (c *Context) GetCurrentTeamMember() *model.TeamMember {
+ return c.Session.GetTeamByTeamId(c.TeamId)
+}
+
func IsApiCall(r *http.Request) bool {
return strings.Index(r.URL.Path, "/api/") == 0
}
diff --git a/api/context_test.go b/api/context_test.go
index c3c7a9768..88ba0f665 100644
--- a/api/context_test.go
+++ b/api/context_test.go
@@ -8,26 +8,6 @@ import (
"testing"
)
-func TestContext(t *testing.T) {
- context := Context{}
-
- context.IpAddress = "127.0.0.1"
- context.Session.UserId = "5"
-
- if !context.HasPermissionsToUser("5", "") {
- t.Fatal("should have permissions")
- }
-
- if context.HasPermissionsToUser("6", "") {
- t.Fatal("shouldn't have permissions")
- }
-
- context.Session.Roles = model.ROLE_SYSTEM_ADMIN
- if !context.HasPermissionsToUser("6", "") {
- t.Fatal("should have permissions")
- }
-}
-
func TestCache(t *testing.T) {
session := &model.Session{
Id: model.NewId(),
diff --git a/api/emoji.go b/api/emoji.go
index d84996230..39f57a3c8 100644
--- a/api/emoji.go
+++ b/api/emoji.go
@@ -182,7 +182,7 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = result.Err
return
} else {
- if c.Session.UserId != result.Data.(*model.Emoji).CreatorId && !c.IsSystemAdmin() {
+ if c.Session.UserId != result.Data.(*model.Emoji).CreatorId && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
c.Err = model.NewLocAppError("deleteEmoji", "api.emoji.delete.permissions.app_error", nil, "user_id="+c.Session.UserId)
c.Err.StatusCode = http.StatusUnauthorized
return
diff --git a/api/file.go b/api/file.go
index 113666270..dd99a8caf 100644
--- a/api/file.go
+++ b/api/file.go
@@ -103,8 +103,6 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
-
files := m.File["files"]
resStruct := &model.FileUploadResponse{
@@ -115,7 +113,7 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
imageNameList := []string{}
imageDataList := [][]byte{}
- if !c.HasPermissionsToChannel(cchan, "uploadFile") {
+ if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_UPLOAD_FILE) {
return
}
@@ -318,7 +316,9 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
+ if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
+ return
+ }
path := "teams/" + c.TeamId + "/channels/" + channelId + "/users/" + userId + "/" + filename
var info *model.FileInfo
@@ -339,10 +339,6 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if !c.HasPermissionsToChannel(cchan, "getFileInfo") {
- return
- }
-
w.Header().Set("Cache-Control", "max-age=2592000, public")
w.Write([]byte(info.ToJson()))
@@ -356,7 +352,7 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
userId := params["user_id"]
filename := params["filename"]
- if !c.HasPermissionsToChannel(Srv.Store.Channel().CheckPermissionsTo(teamId, channelId, c.Session.UserId), "getFile") {
+ if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return
}
@@ -512,14 +508,12 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
userId := matches[0][2]
filename = matches[0][3]
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
-
- url := generatePublicLink(c.GetSiteURL(), c.TeamId, channelId, userId, filename)
-
- if !c.HasPermissionsToChannel(cchan, "getPublicLink") {
+ if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_GET_PUBLIC_LINK) {
return
}
+ url := generatePublicLink(c.GetSiteURL(), c.TeamId, channelId, userId, filename)
+
w.Write([]byte(model.StringToJson(url)))
}
diff --git a/api/license.go b/api/license.go
index b7bf8a234..cff7d7515 100644
--- a/api/license.go
+++ b/api/license.go
@@ -173,14 +173,17 @@ func RemoveLicense() *model.AppError {
}
func getClientLicenceConfig(c *Context, w http.ResponseWriter, r *http.Request) {
- etag := utils.GetClientLicenseEtag(!c.IsSystemAdmin())
+ useSanitizedLicense := !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM)
+ c.Err = nil
+
+ etag := utils.GetClientLicenseEtag(useSanitizedLicense)
if HandleEtag(etag, w, r) {
return
}
var clientLicense map[string]string
- if c.IsSystemAdmin() {
+ if useSanitizedLicense {
clientLicense = utils.ClientLicense
} else {
clientLicense = utils.GetSanitizedClientLicense()
diff --git a/api/oauth.go b/api/oauth.go
index b1c7675ff..18a9979f6 100644
--- a/api/oauth.go
+++ b/api/oauth.go
@@ -53,12 +53,10 @@ func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !c.IsSystemAdmin() {
- c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_OAUTH) {
+ c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
app := model.OAuthAppFromJson(r.Body)
@@ -94,18 +92,14 @@ func getOAuthApps(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- isSystemAdmin := c.IsSystemAdmin()
-
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !isSystemAdmin {
- c.Err = model.NewLocAppError("getOAuthAppsByUser", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_OAUTH) {
+ c.Err = model.NewLocAppError("getOAuthApps", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
var ochan store.StoreChannel
- if isSystemAdmin {
+ if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
ochan = Srv.Store.OAuth().GetApps()
} else {
ochan = Srv.Store.OAuth().GetAppByUser(c.Session.UserId)
@@ -872,14 +866,10 @@ func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- isSystemAdmin := c.IsSystemAdmin()
-
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !isSystemAdmin {
- c.Err = model.NewLocAppError("deleteOAuthApp", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_OAUTH) {
+ c.Err = model.NewLocAppError("deleteOAuthApp", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -896,7 +886,7 @@ func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = result.Err
return
} else {
- if c.Session.UserId != result.Data.(*model.OAuthApp).CreatorId && !isSystemAdmin {
+ if c.Session.UserId != result.Data.(*model.OAuthApp).CreatorId && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("deleteOAuthApp", "api.oauth.delete.permissions.app_error", nil, "user_id="+c.Session.UserId)
return
@@ -964,16 +954,6 @@ func regenerateOAuthSecret(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- isSystemAdmin := c.IsSystemAdmin()
-
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !isSystemAdmin {
- c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
- }
-
params := mux.Vars(r)
id := params["id"]
@@ -989,9 +969,9 @@ func regenerateOAuthSecret(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
app = result.Data.(*model.OAuthApp)
- //validate that is a System Admin or the same user that registered the app
- if !isSystemAdmin && app.CreatorId != c.Session.UserId {
- c.Err = model.NewLocAppError("regenerateOAuthSecret", "api.oauth.regenerate_secret.app_error", nil, "")
+ if app.CreatorId != c.Session.UserId && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
+ c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
return
}
diff --git a/api/oauth_test.go b/api/oauth_test.go
index a54fbc2c3..da069aefe 100644
--- a/api/oauth_test.go
+++ b/api/oauth_test.go
@@ -161,6 +161,7 @@ func TestGetOAuthAppsByUser(t *testing.T) {
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
if result, err := Client.GetOAuthAppsByUser(); err != nil {
t.Fatal(err)
@@ -316,6 +317,7 @@ func TestOAuthDeleteApp(t *testing.T) {
utils.Cfg.ServiceSettings.EnableOAuthServiceProvider = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
app := &model.OAuthApp{Name: "TestApp5" + model.NewId(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
diff --git a/api/post.go b/api/post.go
index 9a11a5c59..c43bc9843 100644
--- a/api/post.go
+++ b/api/post.go
@@ -59,10 +59,24 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
post.UserId = c.Session.UserId
- // Create and save post object to channel
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, post.ChannelId, c.Session.UserId)
+ cchan := Srv.Store.Channel().Get(post.ChannelId)
+
+ if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_CREATE_POST) {
+ return
+ }
+
+ // Check that channel has not been deleted
+ var channel *model.Channel
+ if result := <-cchan; result.Err != nil {
+ c.SetInvalidParam("createPost", "post.channelId")
+ return
+ } else {
+ channel = result.Data.(*model.Channel)
+ }
- if !c.HasPermissionsToChannel(cchan, "createPost") {
+ if channel.DeleteAt != 0 {
+ c.Err = model.NewLocAppError("createPost", "api.post.create_post.can_not_post_to_deleted.error", nil, "")
+ c.Err.StatusCode = http.StatusBadRequest
return
}
@@ -1099,10 +1113,9 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, post.ChannelId, c.Session.UserId)
pchan := Srv.Store.Post().Get(post.Id)
- if !c.HasPermissionsToChannel(cchan, "updatePost") {
+ if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_EDIT_POST) {
return
}
@@ -1204,10 +1217,9 @@ func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
etagChan := Srv.Store.Post().GetEtag(id)
- if !c.HasPermissionsToChannel(cchan, "getPosts") {
+ if !HasPermissionToChannelContext(c, id, model.PERMISSION_CREATE_POST) {
return
}
@@ -1246,10 +1258,9 @@ func getPostsSince(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
pchan := Srv.Store.Post().GetPostsSince(id, time)
- if !c.HasPermissionsToChannel(cchan, "getPostsSince") {
+ if !HasPermissionToChannelContext(c, id, model.PERMISSION_READ_CHANNEL) {
return
}
@@ -1279,10 +1290,9 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
pchan := Srv.Store.Post().Get(postId)
- if !c.HasPermissionsToChannel(cchan, "getPost") {
+ if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return
}
@@ -1326,8 +1336,7 @@ func getPostById(c *Context, w http.ResponseWriter, r *http.Request) {
}
post := list.Posts[list.Order[0]]
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, post.ChannelId, c.Session.UserId)
- if !c.HasPermissionsToChannel(cchan, "getPostById") {
+ if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_READ_CHANNEL) {
return
}
@@ -1361,12 +1370,7 @@ func getPermalinkTmp(c *Context, w http.ResponseWriter, r *http.Request) {
}
post := list.Posts[list.Order[0]]
- if !c.HasPermissionsToTeam(c.TeamId, "permalink") {
- return
- }
-
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, post.ChannelId, c.Session.UserId)
- if !c.HasPermissionsToChannel(cchan, "getPermalinkTmp") {
+ if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_READ_CHANNEL) {
// If we don't have permissions attempt to join the channel to fix the problem
if err, _ := JoinChannelById(c, c.Session.UserId, post.ChannelId); err != nil {
// On error just return with permissions error
@@ -1402,7 +1406,10 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.Session.UserId)
+ if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_EDIT_POST) {
+ return
+ }
+
pchan := Srv.Store.Post().Get(postId)
if result := <-pchan; result.Err != nil {
@@ -1412,10 +1419,6 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
post := result.Data.(*model.PostList).Posts[postId]
- if !c.HasPermissionsToChannel(cchan, "deletePost") && !c.IsTeamAdmin() {
- return
- }
-
if post == nil {
c.SetInvalidParam("deletePost", "postId")
return
@@ -1427,7 +1430,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if post.UserId != c.Session.UserId && !c.IsTeamAdmin() {
+ if post.UserId != c.Session.UserId && !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_EDIT_OTHERS_POSTS) {
c.Err = model.NewLocAppError("deletePost", "api.post.delete_post.permissions.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
@@ -1507,11 +1510,10 @@ func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, b
return
}
- cchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, id, c.Session.UserId)
// We can do better than this etag in this situation
etagChan := Srv.Store.Post().GetEtag(id)
- if !c.HasPermissionsToChannel(cchan, "getPostsBeforeOrAfter") {
+ if !HasPermissionToChannelContext(c, id, model.PERMISSION_READ_CHANNEL) {
return
}
diff --git a/api/post_test.go b/api/post_test.go
index 2239e92cd..8f8bca899 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -778,6 +778,7 @@ func TestDeletePosts(t *testing.T) {
post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post)
th.LoginBasic2()
+ Client.Must(Client.JoinChannel(channel1.Id))
Client.Must(Client.DeletePost(channel1.Id, post4.Id))
}
diff --git a/api/team.go b/api/team.go
index 402a73564..83367f31f 100644
--- a/api/team.go
+++ b/api/team.go
@@ -259,9 +259,18 @@ func JoinUserToTeamById(teamId string, user *model.User) *model.AppError {
func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
- tm := &model.TeamMember{TeamId: team.Id, UserId: user.Id}
+ tm := &model.TeamMember{
+ TeamId: team.Id,
+ UserId: user.Id,
+ Roles: model.ROLE_TEAM_USER.Id,
+ }
+
+ channelRole := model.ROLE_CHANNEL_USER.Id
- channelRole := ""
+ if team.Email == user.Email {
+ tm.Roles = model.ROLE_TEAM_USER.Id + " " + model.ROLE_TEAM_ADMIN.Id
+ channelRole = model.ROLE_CHANNEL_USER.Id + " " + model.ROLE_CHANNEL_ADMIN.Id
+ }
if etmr := <-Srv.Store.Team().GetMember(team.Id, user.Id); etmr.Err == nil {
// Membership alredy exists. Check if deleted and and update, otherwise do nothing
@@ -276,11 +285,6 @@ func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
return tmr.Err
}
} else {
- if team.Email == user.Email {
- tm.Roles = model.ROLE_TEAM_ADMIN
- channelRole = model.CHANNEL_ROLE_ADMIN
- }
-
// Membership appears to be missing. Lets try to add.
if tmr := <-Srv.Store.Team().SaveMember(tm); tmr.Err != nil {
return tmr.Err
@@ -361,7 +365,7 @@ func isTeamCreationAllowed(c *Context, email string) bool {
email = strings.ToLower(email)
- if !c.IsSystemAdmin() && !utils.Cfg.TeamSettings.EnableTeamCreation {
+ if !utils.Cfg.TeamSettings.EnableTeamCreation && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
c.Err = model.NewLocAppError("isTeamCreationAllowed", "api.team.is_team_creation_allowed.disabled.app_error", nil, "")
return false
}
@@ -402,9 +406,10 @@ func GetAllTeamListings(c *Context, w http.ResponseWriter, r *http.Request) {
m := make(map[string]*model.Team)
for _, v := range teams {
m[v.Id] = v
- if !c.IsSystemAdmin() {
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
m[v.Id].Sanitize()
}
+ c.Err = nil
}
w.Write([]byte(model.TeamMapToJson(m)))
@@ -415,9 +420,10 @@ func GetAllTeamListings(c *Context, w http.ResponseWriter, r *http.Request) {
// on the server. Otherwise, it will only be the teams of which the user is a member.
func getAll(c *Context, w http.ResponseWriter, r *http.Request) {
var tchan store.StoreChannel
- if c.IsSystemAdmin() {
+ if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
tchan = Srv.Store.Team().GetAll()
} else {
+ c.Err = nil
tchan = Srv.Store.Team().GetTeamsByUserId(c.Session.UserId)
}
@@ -472,13 +478,14 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
}
if utils.IsLicensed {
- if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_SYSTEM_ADMIN && !c.IsSystemAdmin() {
- c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_system_admin.app_error", nil, "")
- return
- }
-
- if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_TEAM_ADMIN && !c.IsTeamAdmin() {
- c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_team_admin.app_error", nil, "")
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_INVITE_USER) {
+ if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_SYSTEM_ADMIN {
+ c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_system_admin.app_error", nil, "")
+ }
+ if *utils.Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_TEAM_ADMIN {
+ c.Err = model.NewLocAppError("inviteMembers", "api.team.invite_members.restricted_team_admin.app_error", nil, "")
+ }
+ c.Err.StatusCode = http.StatusForbidden
return
}
}
@@ -540,9 +547,7 @@ func addUserToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
user = result.Data.(*model.User)
}
- if !c.IsTeamAdmin() {
- c.Err = model.NewLocAppError("addUserToTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId)
- c.Err.StatusCode = http.StatusForbidden
+ if !HasPermissionToTeamContext(c, team.Id, model.PERMISSION_ADD_USER_TO_TEAM) {
return
}
@@ -584,9 +589,7 @@ func removeUserFromTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
if c.Session.UserId != user.Id {
- if !c.IsTeamAdmin() {
- c.Err = model.NewLocAppError("removeUserFromTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId)
- c.Err.StatusCode = http.StatusForbidden
+ if !HasPermissionToTeamContext(c, team.Id, model.PERMISSION_REMOVE_USER_FROM_TEAM) {
return
}
}
@@ -703,12 +706,7 @@ func InviteMembers(c *Context, team *model.Team, user *model.User, invites []str
sender := user.GetDisplayName()
- senderRole := ""
- if c.IsTeamAdmin() {
- senderRole = c.T("api.team.invite_members.admin")
- } else {
- senderRole = c.T("api.team.invite_members.member")
- }
+ senderRole := c.T("api.team.invite_members.member")
subjectPage := utils.NewHTMLTemplate("invite_subject", c.Locale)
subjectPage.Props["Subject"] = c.T("api.templates.invite_subject",
@@ -755,7 +753,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
team.Id = c.TeamId
- if !c.IsTeamAdmin() {
+ if !HasPermissionToTeamContext(c, team.Id, model.PERMISSION_MANAGE_TEAM) {
c.Err = model.NewLocAppError("updateTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden
return
@@ -833,7 +831,7 @@ func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
- if !c.HasPermissionsToTeam(c.TeamId, "import") || !c.IsTeamAdmin() {
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_IMPORT_TEAM) {
c.Err = model.NewLocAppError("importTeam", "api.team.import_team.admin.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden
return
@@ -930,7 +928,7 @@ func getMembers(c *Context, w http.ResponseWriter, r *http.Request) {
id := params["id"]
if c.Session.GetTeamByTeamId(id) == nil {
- if !c.HasSystemAdminPermissions("getMembers") {
+ if !HasPermissionToTeamContext(c, id, model.PERMISSION_MANAGE_SYSTEM) {
return
}
}
diff --git a/api/team_test.go b/api/team_test.go
index ade65edcd..1a754b5e6 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -175,14 +175,14 @@ func TestRemoveUserFromTeam(t *testing.T) {
t.Fatal("should fail not enough permissions")
} else {
if err.Id != "api.context.permissions.app_error" {
- t.Fatal("wrong error")
+ t.Fatal("wrong error. Got: " + err.Id)
}
}
if _, err := th.BasicClient.RemoveUserFromTeam("", th.SystemAdminUser.Id); err == nil {
t.Fatal("should fail not enough permissions")
} else {
- if err.Id != "api.team.update_team.permissions.app_error" {
+ if err.Id != "api.context.permissions.app_error" {
t.Fatal("wrong error")
}
}
@@ -318,7 +318,7 @@ func TestGetAllTeamListings(t *testing.T) {
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- UpdateUserRoles(c, user, model.ROLE_SYSTEM_ADMIN)
+ UpdateUserRoles(c, user, model.ROLE_SYSTEM_ADMIN.Id)
Client.Login(user.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -415,8 +415,10 @@ func TestInviteMembers(t *testing.T) {
restrictTeamInvite := *utils.Cfg.TeamSettings.RestrictTeamInvite
defer func() {
*utils.Cfg.TeamSettings.RestrictTeamInvite = restrictTeamInvite
+ utils.SetDefaultRolesBasedOnConfig()
}()
*utils.Cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_TEAM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
th.LoginBasic2()
LinkUserToTeam(th.BasicUser2, team)
@@ -445,6 +447,7 @@ func TestInviteMembers(t *testing.T) {
}
*utils.Cfg.TeamSettings.RestrictTeamInvite = model.PERMISSIONS_SYSTEM_ADMIN
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.InviteMembers(invites); err == nil {
t.Fatal("should have errored not system admin and licensed")
diff --git a/api/user.go b/api/user.go
index a33e2f7d7..adcc44f30 100644
--- a/api/user.go
+++ b/api/user.go
@@ -230,16 +230,16 @@ func IsVerifyHashRequired(user *model.User, team *model.Team, hash string) bool
func CreateUser(user *model.User) (*model.User, *model.AppError) {
- user.Roles = ""
+ user.Roles = model.ROLE_SYSTEM_USER.Id
// Below is a special case where the first user in the entire
- // system is granted the system_admin role instead of admin
+ // system is granted the system_admin role
if result := <-Srv.Store.User().GetTotalUsersCount(); result.Err != nil {
return nil, result.Err
} else {
count := result.Data.(int64)
if count <= 0 {
- user.Roles = model.ROLE_SYSTEM_ADMIN
+ user.Roles = model.ROLE_SYSTEM_ADMIN.Id + " " + model.ROLE_SYSTEM_USER.Id
}
}
@@ -561,7 +561,7 @@ func LoginByOAuth(c *Context, w http.ResponseWriter, r *http.Request, service st
// User MUST be authenticated completely before calling Login
func doLogin(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, deviceId string) {
- session := &model.Session{UserId: user.Id, Roles: user.Roles, DeviceId: deviceId, IsOAuth: false}
+ session := &model.Session{UserId: user.Id, Roles: user.GetRawRoles(), DeviceId: deviceId, IsOAuth: false}
maxAge := *utils.Cfg.ServiceSettings.SessionLengthWebInDays * 60 * 60 * 24
@@ -788,7 +788,7 @@ func getSessions(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["user_id"]
- if !c.HasPermissionsToUser(id, "getSessions") {
+ if !HasPermissionToUser(c, id) {
return
}
@@ -918,11 +918,12 @@ func getInitialLoad(c *Context, w http.ResponseWriter, r *http.Request) {
}
il.ClientCfg = utils.ClientCfg
- if c.IsSystemAdmin() {
+ if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
il.LicenseCfg = utils.ClientLicense
} else {
il.LicenseCfg = utils.GetSanitizedClientLicense()
}
+ c.Err = nil
w.Write([]byte(il.ToJson()))
}
@@ -931,7 +932,7 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["user_id"]
- if !c.HasPermissionsToUser(id, "getUser") {
+ if !HasPermissionToUser(c, id) {
return
}
@@ -956,7 +957,7 @@ func getProfilesForDirectMessageList(c *Context, w http.ResponseWriter, r *http.
if *utils.Cfg.TeamSettings.RestrictDirectMessage == model.DIRECT_MESSAGE_TEAM {
if c.Session.GetTeamByTeamId(id) == nil {
- if !c.HasSystemAdminPermissions("getProfiles") {
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
return
}
}
@@ -985,7 +986,7 @@ func getProfiles(c *Context, w http.ResponseWriter, r *http.Request) {
id := params["id"]
if c.Session.GetTeamByTeamId(id) == nil {
- if !c.HasSystemAdminPermissions("getProfiles") {
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
return
}
}
@@ -1035,7 +1036,7 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["user_id"]
- if !c.HasPermissionsToUser(id, "getAudits") {
+ if !HasPermissionToUser(c, id) {
return
}
@@ -1292,7 +1293,7 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if !c.HasPermissionsToUser(user.Id, "updateUser") {
+ if !HasPermissionToUser(c, user.Id) {
return
}
@@ -1432,22 +1433,21 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
}
new_roles := props["new_roles"]
- if !(model.IsValidUserRoles(new_roles) || model.IsValidTeamRoles(new_roles)) {
+ if !(model.IsValidUserRoles(new_roles)) {
c.SetInvalidParam("updateRoles", "new_roles")
return
}
// If you are not the team admin then you can only demote yourself
- if !c.IsTeamAdmin() && user_id != c.Session.UserId {
+ if user_id != c.Session.UserId && !HasPermissionToTeamContext(c, team_id, model.PERMISSION_MANAGE_ROLES) {
c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.team_admin_needed.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
- // Only another system admin can add the system admin role
- if model.IsInRole(new_roles, model.ROLE_SYSTEM_ADMIN) && !c.IsSystemAdmin() {
+ // If your trying to assign the system admin role, you must have that permission
+ if model.IsInRole(new_roles, model.ROLE_SYSTEM_ADMIN.Id) && !HasPermissionToContext(c, model.PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE) {
c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.system_admin_set.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
return
}
@@ -1459,15 +1459,15 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
user = result.Data.(*model.User)
}
- // only another system admin can remove another system admin
- if model.IsInRole(user.Roles, model.ROLE_SYSTEM_ADMIN) && !c.IsSystemAdmin() {
+ // only another system admin can modify another system admin
+ if model.IsInRole(user.GetRawRoles(), model.ROLE_SYSTEM_ADMIN.Id) && !HasPermissionToContext(c, model.PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE) {
c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.system_admin_needed.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
// if the team role has changed then lets update team members
- if model.IsValidTeamRoles(new_roles) && len(team_id) > 0 {
+ if len(team_id) > 0 {
var members []*model.TeamMember
if result := <-Srv.Store.Team().GetTeamsForUser(user_id); result.Err != nil {
@@ -1489,7 +1489,7 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if !c.IsSystemAdmin() {
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
currentUserTeamMember := c.Session.GetTeamByTeamId(team_id)
// Only the system admin can modify other team
@@ -1500,12 +1500,13 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
}
// Only another team admin can make a team admin
- if !currentUserTeamMember.IsTeamAdmin() && model.IsInRole(new_roles, model.ROLE_TEAM_ADMIN) {
+ if model.IsInRole(new_roles, model.ROLE_TEAM_ADMIN.Id) && !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_ROLES) {
c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.team_admin_needed.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
}
+ c.Err = nil
member.Roles = new_roles
@@ -1513,10 +1514,8 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = result.Err
return
}
- }
-
- // If the users role has changed then lets update the user
- if model.IsValidUserRoles(new_roles) {
+ } else {
+ // If the users role has changed then lets update the user
UpdateUserRoles(c, user, new_roles)
if c.Err != nil {
return
@@ -1575,7 +1574,7 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
// true when you're trying to de-activate yourself
isSelfDeactive := !active && user_id == c.Session.UserId
- if !isSelfDeactive && !c.IsSystemAdmin() {
+ if !isSelfDeactive && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
c.Err = model.NewLocAppError("updateActive", "api.user.update_active.permissions.app_error", nil, "userId="+user_id)
c.Err.StatusCode = http.StatusForbidden
return
@@ -1626,7 +1625,7 @@ func PermanentDeleteUser(c *Context, user *model.User) *model.AppError {
c.Path = "/users/permanent_delete"
c.LogAuditWithUserId(user.Id, fmt.Sprintf("attempt userId=%v", user.Id))
c.LogAuditWithUserId("", fmt.Sprintf("attempt userId=%v", user.Id))
- if user.IsInRole(model.ROLE_SYSTEM_ADMIN) {
+ if user.IsInRole(model.ROLE_SYSTEM_ADMIN.Id) {
l4g.Warn(utils.T("api.user.permanent_delete_user.system_admin.warn"), user.Email)
}
@@ -1814,7 +1813,7 @@ func ResetPassword(c *Context, userId, newPassword string) *model.AppError {
user = result.Data.(*model.User)
}
- if user.AuthData != nil && len(*user.AuthData) != 0 && !c.IsSystemAdmin() {
+ if user.AuthData != nil && len(*user.AuthData) != 0 && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
return model.NewLocAppError("ResetPassword", "api.user.reset_password.sso.app_error", nil, "userId="+user.Id)
}
@@ -1911,7 +1910,7 @@ func updateUserNotify(c *Context, w http.ResponseWriter, r *http.Request) {
uchan := Srv.Store.User().Get(user_id)
- if !c.HasPermissionsToUser(user_id, "updateUserNotify") {
+ if !HasPermissionToUser(c, user_id) {
return
}
@@ -2567,10 +2566,11 @@ func userTyping(req *model.WebSocketRequest) (map[string]interface{}, *model.App
func sanitizeProfile(c *Context, user *model.User) *model.User {
options := utils.Cfg.GetSanitizeOptions()
- if c.IsSystemAdmin() {
+ if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
options["email"] = true
options["fullname"] = true
}
+ c.Err = nil
user.SanitizeProfile(options)
diff --git a/api/user_test.go b/api/user_test.go
index 15397ff0f..d2c15f730 100644
--- a/api/user_test.go
+++ b/api/user_test.go
@@ -420,7 +420,7 @@ func TestGetUser(t *testing.T) {
c := &Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- UpdateUserRoles(c, ruser.Data.(*model.User), model.ROLE_SYSTEM_ADMIN)
+ UpdateUserRoles(c, ruser.Data.(*model.User), model.ROLE_SYSTEM_ADMIN.Id)
Client.Login(user.Email, "passwd1")
@@ -748,7 +748,7 @@ func TestUserUpdate(t *testing.T) {
Client.SetTeamId(team.Id)
user.Nickname = "Jim Jimmy"
- user.Roles = model.ROLE_TEAM_ADMIN
+ user.Roles = model.ROLE_SYSTEM_ADMIN.Id
user.LastPasswordUpdate = 123
if result, err := Client.UpdateUser(user); err != nil {
@@ -757,7 +757,7 @@ func TestUserUpdate(t *testing.T) {
if result.Data.(*model.User).Nickname != "Jim Jimmy" {
t.Fatal("Nickname did not update properly")
}
- if result.Data.(*model.User).Roles != "" {
+ if result.Data.(*model.User).Roles != model.ROLE_SYSTEM_USER.Id {
t.Fatal("Roles should not have updated")
}
if result.Data.(*model.User).LastPasswordUpdate == 123 {
@@ -957,7 +957,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// user 1 is trying to promote user 2
data["user_id"] = th.BasicUser2.Id
- data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["new_roles"] = model.ROLE_TEAM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
t.Fatal("Should have errored, you can only demote yourself")
@@ -965,7 +965,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// user 1 is trying to promote user 2
data["user_id"] = th.BasicUser2.Id
- data["new_roles"] = model.ROLE_SYSTEM_ADMIN
+ data["new_roles"] = model.ROLE_SYSTEM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
t.Fatal("Should have errored, you can only demote yourself")
@@ -973,7 +973,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// user 1 is trying to promote himself
data["user_id"] = th.BasicUser.Id
- data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["new_roles"] = model.ROLE_TEAM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
t.Fatal("Should have errored, you cannot elevate your permissions")
@@ -981,7 +981,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// user 1 is trying to promote himself
data["user_id"] = th.BasicUser.Id
- data["new_roles"] = model.ROLE_SYSTEM_ADMIN
+ data["new_roles"] = model.ROLE_SYSTEM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
t.Fatal("Should have errored, you cannot elevate your permissions")
@@ -991,7 +991,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// promote user to team admin
data["user_id"] = th.BasicUser.Id
- data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["new_roles"] = model.ROLE_TEAM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.SystemAdminClient.UpdateUserRoles(data); err != nil {
t.Fatal("Should have succeeded since they are system admin")
@@ -1007,7 +1007,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// re-promote user to team admin
data["user_id"] = th.BasicUser.Id
- data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["new_roles"] = model.ROLE_TEAM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.SystemAdminClient.UpdateUserRoles(data); err != nil {
t.Fatal("Should have succeeded since they are system admin")
@@ -1015,7 +1015,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// user 1 is promoting user 2 to team admin
data["user_id"] = th.BasicUser2.Id
- data["new_roles"] = model.ROLE_TEAM_ADMIN
+ data["new_roles"] = model.ROLE_TEAM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.BasicClient.UpdateUserRoles(data); err != nil {
t.Fatal("Should have succeeded since they are team admin")
@@ -1023,7 +1023,7 @@ func TestUserUpdateRolesMoreCases(t *testing.T) {
// user 1 is trying to promote user 2 from team admin to system admin
data["user_id"] = th.BasicUser2.Id
- data["new_roles"] = model.ROLE_SYSTEM_ADMIN
+ data["new_roles"] = model.ROLE_SYSTEM_ADMIN.Id
data["team_id"] = th.BasicTeam.Id
if _, err := th.BasicClient.UpdateUserRoles(data); err == nil {
t.Fatal("Should have errored, can only be system admin")
diff --git a/api/webhook.go b/api/webhook.go
index a9eded2ac..2995a4a9d 100644
--- a/api/webhook.go
+++ b/api/webhook.go
@@ -41,12 +41,8 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("createIncomingHook", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_WEBHOOKS) {
+ return
}
c.LogAudit("attempt")
@@ -59,7 +55,6 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
}
cchan := Srv.Store.Channel().Get(hook.ChannelId)
- pchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, hook.ChannelId, c.Session.UserId)
hook.UserId = c.Session.UserId
hook.TeamId = c.TeamId
@@ -72,12 +67,9 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
channel = result.Data.(*model.Channel)
}
- if !c.HasPermissionsToChannel(pchan, "createIncomingHook") {
- if channel.Type != model.CHANNEL_OPEN || channel.TeamId != c.TeamId {
- c.LogAudit("fail - bad channel permissions")
- return
- }
- c.Err = nil
+ if channel.Type != model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) {
+ c.LogAudit("fail - bad channel permissions")
+ return
}
if result := <-Srv.Store.Webhook().SaveIncoming(hook); result.Err != nil {
@@ -97,12 +89,10 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("deleteIncomingHook", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.Err = model.NewLocAppError("deleteIncomingHook", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -119,7 +109,7 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = result.Err
return
} else {
- if c.Session.UserId != result.Data.(*model.IncomingWebhook).UserId && !c.IsTeamAdmin() {
+ if c.Session.UserId != result.Data.(*model.IncomingWebhook).UserId && !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_OTHERS_WEBHOOKS) {
c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("deleteIncomingHook", "api.webhook.delete_incoming.permissions.app_errror", nil, "user_id="+c.Session.UserId)
return
@@ -142,12 +132,10 @@ func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("getIncomingHooks", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.Err = model.NewLocAppError("getIncomingHooks", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
if result := <-Srv.Store.Webhook().GetIncomingByTeam(c.TeamId); result.Err != nil {
@@ -166,12 +154,10 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("createOutgoingHook", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.Err = model.NewLocAppError("createOutgoingHook", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -188,7 +174,6 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
if len(hook.ChannelId) != 0 {
cchan := Srv.Store.Channel().Get(hook.ChannelId)
- pchan := Srv.Store.Channel().CheckPermissionsTo(c.TeamId, hook.ChannelId, c.Session.UserId)
var channel *model.Channel
if result := <-cchan; result.Err != nil {
@@ -204,14 +189,10 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if !c.HasPermissionsToChannel(pchan, "createOutgoingHook") {
- if channel.Type != model.CHANNEL_OPEN || channel.TeamId != c.TeamId {
- c.LogAudit("fail - bad channel permissions")
- c.Err = model.NewLocAppError("createOutgoingHook", "api.webhook.create_outgoing.permissions.app_error", nil, "")
- return
- } else {
- c.Err = nil
- }
+ if channel.Type != model.CHANNEL_OPEN || channel.TeamId != c.TeamId {
+ c.LogAudit("fail - bad channel permissions")
+ c.Err = model.NewLocAppError("createOutgoingHook", "api.webhook.create_outgoing.permissions.app_error", nil, "")
+ return
}
} else if len(hook.TriggerWords) == 0 {
c.Err = model.NewLocAppError("createOutgoingHook", "api.webhook.create_outgoing.triggers.app_error", nil, "")
@@ -252,12 +233,10 @@ func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("getOutgoingHooks", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.Err = model.NewLocAppError("getOutgoingHooks", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
if result := <-Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId); result.Err != nil {
@@ -276,12 +255,10 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("deleteOutgoingHook", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.Err = model.NewLocAppError("deleteOutgoingHook", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -298,7 +275,7 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = result.Err
return
} else {
- if c.Session.UserId != result.Data.(*model.OutgoingWebhook).CreatorId && !c.IsTeamAdmin() {
+ if c.Session.UserId != result.Data.(*model.OutgoingWebhook).CreatorId && !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_OTHERS_WEBHOOKS) {
c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("deleteOutgoingHook", "api.webhook.delete_outgoing.permissions.app_error", nil, "user_id="+c.Session.UserId)
return
@@ -321,12 +298,10 @@ func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request)
return
}
- if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
- if !(c.IsSystemAdmin() || c.IsTeamAdmin()) {
- c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
+ if !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.command.admin_only.app_error", nil, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
}
c.LogAudit("attempt")
@@ -346,7 +321,7 @@ func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request)
} else {
hook = result.Data.(*model.OutgoingWebhook)
- if c.TeamId != hook.TeamId && c.Session.UserId != hook.CreatorId && !c.IsTeamAdmin() {
+ if c.TeamId != hook.TeamId && c.Session.UserId != hook.CreatorId && !HasPermissionToCurrentTeamContext(c, model.PERMISSION_MANAGE_OTHERS_WEBHOOKS) {
c.LogAudit("fail - inappropriate permissions")
c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.webhook.regen_outgoing_token.permissions.app_error", nil, "user_id="+c.Session.UserId)
return
@@ -465,18 +440,20 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
channel = result.Data.(*model.Channel)
}
- pchan := Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)
-
// create a mock session
c.Session = model.Session{
- UserId: hook.UserId,
- TeamMembers: []*model.TeamMember{{TeamId: hook.TeamId, UserId: hook.UserId}},
- IsOAuth: false,
+ UserId: hook.UserId,
+ TeamMembers: []*model.TeamMember{{
+ TeamId: hook.TeamId,
+ UserId: hook.UserId,
+ Roles: model.ROLE_CHANNEL_USER.Id,
+ }},
+ IsOAuth: false,
}
c.TeamId = hook.TeamId
- if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
+ if channel.Type != model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) {
c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "")
return
}
diff --git a/api/webhook_test.go b/api/webhook_test.go
index f2375fb19..b3fa04d88 100644
--- a/api/webhook_test.go
+++ b/api/webhook_test.go
@@ -26,9 +26,11 @@ func TestCreateIncomingHook(t *testing.T) {
defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
}()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
hook := &model.IncomingWebhook{ChannelId: channel1.Id}
@@ -85,7 +87,17 @@ func TestCreateIncomingHook(t *testing.T) {
t.Fatal("should have failed - not system/team admin")
}
+ Client.Logout()
+ UpdateUserToTeamAdmin(user2, team)
+ Client.Must(Client.LoginById(user2.Id, user2.Password))
+ Client.SetTeamId(team.Id)
+
+ if _, err := Client.CreateIncomingWebhook(hook); err != nil {
+ t.Fatal(err)
+ }
+
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.CreateIncomingWebhook(hook); err != nil {
t.Fatal(err)
@@ -117,9 +129,11 @@ func TestListIncomingHooks(t *testing.T) {
defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
}()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
hook1 := &model.IncomingWebhook{ChannelId: channel1.Id}
hook1 = Client.Must(Client.CreateIncomingWebhook(hook1)).Data.(*model.IncomingWebhook)
@@ -146,6 +160,7 @@ func TestListIncomingHooks(t *testing.T) {
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.ListIncomingWebhooks(); err != nil {
t.Fatal(err)
@@ -171,9 +186,11 @@ func TestDeleteIncomingHook(t *testing.T) {
defer func() {
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = enableIncomingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
}()
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
hook := &model.IncomingWebhook{ChannelId: channel1.Id}
hook = Client.Must(Client.CreateIncomingWebhook(hook)).Data.(*model.IncomingWebhook)
@@ -207,6 +224,7 @@ func TestDeleteIncomingHook(t *testing.T) {
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.DeleteIncomingWebhook(hook.Id); err == nil {
t.Fatal("should have failed - not creator or team admin")
@@ -244,9 +262,11 @@ func TestCreateOutgoingHook(t *testing.T) {
defer func() {
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
}()
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
@@ -317,6 +337,7 @@ func TestCreateOutgoingHook(t *testing.T) {
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.CreateOutgoingWebhook(hook); err != nil {
t.Fatal(err)
@@ -350,9 +371,11 @@ func TestListOutgoingHooks(t *testing.T) {
defer func() {
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
}()
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
hook1 := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook1 = Client.Must(Client.CreateOutgoingWebhook(hook1)).Data.(*model.OutgoingWebhook)
@@ -379,6 +402,7 @@ func TestListOutgoingHooks(t *testing.T) {
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.ListOutgoingWebhooks(); err != nil {
t.Fatal(err)
@@ -404,9 +428,11 @@ func TestDeleteOutgoingHook(t *testing.T) {
defer func() {
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
}()
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
@@ -440,6 +466,7 @@ func TestDeleteOutgoingHook(t *testing.T) {
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
if _, err := Client.DeleteOutgoingWebhook(hook.Id); err == nil {
t.Fatal("should have failed - not creator or team admin")
@@ -475,9 +502,11 @@ func TestRegenOutgoingHookToken(t *testing.T) {
defer func() {
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
}()
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
hook := &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
@@ -507,6 +536,7 @@ func TestRegenOutgoingHookToken(t *testing.T) {
}
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
hook = &model.OutgoingWebhook{ChannelId: channel1.Id, CallbackURLs: []string{"http://nowhere.com"}}
hook = Client.Must(Client.CreateOutgoingWebhook(hook)).Data.(*model.OutgoingWebhook)
diff --git a/i18n/en.json b/i18n/en.json
index 32f55a6df..5306be466 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -48,8 +48,24 @@
"translation": "September"
},
{
- "id": "api.admin.add_certificate.array.app_error",
- "translation": "Empty array under 'certificate' in request"
+ "id": "authentication.permissions.team_invite_user.name",
+ "translation": "Invite User"
+ },
+ {
+ "id": "authentication.permissions.team_invite_user.description",
+ "translation": "Ability to invite users to a team"
+ },
+ {
+ "id": "authentication.permissions.team_use_slash_commands.name",
+ "translation": "User Slash Commands"
+ },
+ {
+ "id": "authentication.permissions.team_use_slash_commands.description",
+ "translation": "Ability to user slash commands"
+ },
+ {
+ "id": "api.auth.unable_to_get_user.app_error",
+ "translation": "Unable to get user to check permissions."
},
{
"id": "api.admin.add_certificate.no_file.app_error",
@@ -1154,6 +1170,10 @@
"translation": "Bad filename discarded, filename=%v"
},
{
+ "id": "api.post.create_post.can_not_post_to_deleted.error",
+ "translation": "Can not post to deleted channel."
+ },
+ {
"id": "api.post.create_post.channel_root_id.app_error",
"translation": "Invalid ChannelId for RootId parameter"
},
diff --git a/mattermost.go b/mattermost.go
index 6d6130604..73fd472ef 100644
--- a/mattermost.go
+++ b/mattermost.go
@@ -437,6 +437,7 @@ func setupClientTests() {
*utils.Cfg.ServiceSettings.EnableCustomEmoji = true
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = false
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false
+ utils.SetDefaultRolesBasedOnConfig()
}
func executeTestCommand(cmd *exec.Cmd) {
diff --git a/model/authorization.go b/model/authorization.go
new file mode 100644
index 000000000..a4d8bed86
--- /dev/null
+++ b/model/authorization.go
@@ -0,0 +1,371 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+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"`
+}
+
+var PERMISSION_INVITE_USER *Permission
+var PERMISSION_ADD_USER_TO_TEAM *Permission
+var PERMISSION_USE_SLASH_COMMANDS *Permission
+var PERMISSION_MANAGE_SLASH_COMMANDS *Permission
+var PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS *Permission
+var PERMISSION_CREATE_PUBLIC_CHANNEL *Permission
+var PERMISSION_CREATE_PRIVATE_CHANNEL *Permission
+var PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS *Permission
+var PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS *Permission
+var PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE *Permission
+var PERMISSION_MANAGE_ROLES *Permission
+var PERMISSION_CREATE_DIRECT_CHANNEL *Permission
+var PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES *Permission
+var PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES *Permission
+var PERMISSION_LIST_TEAM_CHANNELS *Permission
+var PERMISSION_JOIN_PUBLIC_CHANNELS *Permission
+var PERMISSION_DELETE_PUBLIC_CHANNEL *Permission
+var PERMISSION_DELETE_PRIVATE_CHANNEL *Permission
+var PERMISSION_EDIT_OTHER_USERS *Permission
+var PERMISSION_READ_CHANNEL *Permission
+var PERMISSION_PERMANENT_DELETE_USER *Permission
+var PERMISSION_UPLOAD_FILE *Permission
+var PERMISSION_GET_PUBLIC_LINK *Permission
+var PERMISSION_MANAGE_WEBHOOKS *Permission
+var PERMISSION_MANAGE_OTHERS_WEBHOOKS *Permission
+var PERMISSION_MANAGE_OAUTH *Permission
+var PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH *Permission
+var PERMISSION_CREATE_POST *Permission
+var PERMISSION_EDIT_POST *Permission
+var PERMISSION_EDIT_OTHERS_POSTS *Permission
+var PERMISSION_REMOVE_USER_FROM_TEAM *Permission
+var PERMISSION_MANAGE_TEAM *Permission
+var PERMISSION_IMPORT_TEAM *Permission
+
+// General permission that encompases 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
+
+var ROLE_SYSTEM_USER *Role
+var ROLE_SYSTEM_ADMIN *Role
+
+var ROLE_TEAM_USER *Role
+var ROLE_TEAM_ADMIN *Role
+
+var ROLE_CHANNEL_USER *Role
+var ROLE_CHANNEL_ADMIN *Role
+var ROLE_CHANNEL_GUEST *Role
+
+var BuiltInRoles map[string]*Role
+
+func InitalizePermissions() {
+ PERMISSION_INVITE_USER = &Permission{
+ "invite_user",
+ "authentication.permissions.team_invite_user.name",
+ "authentication.permissions.team_invite_user.description",
+ }
+ 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_USE_SLASH_COMMANDS = &Permission{
+ "use_slash_commands",
+ "authentication.permissions.team_use_slash_commands.name",
+ "authentication.permissions.team_use_slash_commands.description",
+ }
+ PERMISSION_MANAGE_SLASH_COMMANDS = &Permission{
+ "manage_slash_commands",
+ "authentication.permissions.manage_slash_commands.name",
+ "authentication.permissions.manage_slash_commands.description",
+ }
+ 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_CREATE_PUBLIC_CHANNEL = &Permission{
+ "create_public_channel",
+ "authentication.permissions.create_public_channel.name",
+ "authentication.permissions.create_public_channel.description",
+ }
+ PERMISSION_CREATE_PRIVATE_CHANNEL = &Permission{
+ "create_private_channel",
+ "authentication.permissions.create_private_channel.name",
+ "authentication.permissions.create_private_channel.description",
+ }
+ 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_MANAGE_PRIVATE_CHANNEL_MEMBERS = &Permission{
+ "manage_private_channel_members",
+ "authentication.permissions.manage_private_channel_members.name",
+ "authentication.permissions.manage_private_channel_members.description",
+ }
+ 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_MANAGE_ROLES = &Permission{
+ "manage_roles",
+ "authentication.permissions.manage_roles.name",
+ "authentication.permissions.manage_roles.description",
+ }
+ PERMISSION_MANAGE_SYSTEM = &Permission{
+ "manage_system",
+ "authentication.permissions.manage_system.name",
+ "authentication.permissions.manage_system.description",
+ }
+ PERMISSION_CREATE_DIRECT_CHANNEL = &Permission{
+ "create_direct_channel",
+ "authentication.permissions.create_direct_channel.name",
+ "authentication.permissions.create_direct_channel.description",
+ }
+ PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = &Permission{
+ "manage__publicchannel_properties",
+ "authentication.permissions.manage_public_channel_properties.name",
+ "authentication.permissions.manage_public_channel_properties.description",
+ }
+ 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_LIST_TEAM_CHANNELS = &Permission{
+ "list_team_channels",
+ "authentication.permissions.list_team_channels.name",
+ "authentication.permissions.list_team_channels.description",
+ }
+ PERMISSION_JOIN_PUBLIC_CHANNELS = &Permission{
+ "join_public_channels",
+ "authentication.permissions.join_public_channels.name",
+ "authentication.permissions.join_public_channels.description",
+ }
+ PERMISSION_DELETE_PUBLIC_CHANNEL = &Permission{
+ "delete_public_channel",
+ "authentication.permissions.delete_public_channel.name",
+ "authentication.permissions.delete_public_channel.description",
+ }
+ PERMISSION_DELETE_PRIVATE_CHANNEL = &Permission{
+ "delete_private_channel",
+ "authentication.permissions.delete_private_channel.name",
+ "authentication.permissions.delete_private_channel.description",
+ }
+ PERMISSION_EDIT_OTHER_USERS = &Permission{
+ "edit_other_users",
+ "authentication.permissions.edit_other_users.name",
+ "authentication.permissions.edit_other_users.description",
+ }
+ PERMISSION_READ_CHANNEL = &Permission{
+ "read_channel",
+ "authentication.permissions.read_channel.name",
+ "authentication.permissions.read_channel.description",
+ }
+ PERMISSION_PERMANENT_DELETE_USER = &Permission{
+ "permanent_delete_user",
+ "authentication.permissions.permanent_delete_user.name",
+ "authentication.permissions.permanent_delete_user.description",
+ }
+ PERMISSION_UPLOAD_FILE = &Permission{
+ "upload_file",
+ "authentication.permissions.upload_file.name",
+ "authentication.permissions.upload_file.description",
+ }
+ PERMISSION_GET_PUBLIC_LINK = &Permission{
+ "get_public_link",
+ "authentication.permissions.get_public_link.name",
+ "authentication.permissions.get_public_link.description",
+ }
+ PERMISSION_MANAGE_WEBHOOKS = &Permission{
+ "manage_webhooks",
+ "authentication.permissions.manage_webhooks.name",
+ "authentication.permissions.manage_webhooks.description",
+ }
+ PERMISSION_MANAGE_OTHERS_WEBHOOKS = &Permission{
+ "manage_others_webhooks",
+ "authentication.permissions.manage_others_webhooks.name",
+ "authentication.permissions.manage_others_webhooks.description",
+ }
+ PERMISSION_MANAGE_OAUTH = &Permission{
+ "manage_oauth",
+ "authentication.permissions.manage_oauth.name",
+ "authentication.permissions.manage_oauth.description",
+ }
+ 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_CREATE_POST = &Permission{
+ "create_post",
+ "authentication.permissions.create_post.name",
+ "authentication.permissions.create_post.description",
+ }
+ PERMISSION_EDIT_POST = &Permission{
+ "edit_post",
+ "authentication.permissions.edit_post.name",
+ "authentication.permissions.edit_post.description",
+ }
+ PERMISSION_EDIT_OTHERS_POSTS = &Permission{
+ "edit_others_posts",
+ "authentication.permissions.edit_others_posts.name",
+ "authentication.permissions.edit_others_posts.description",
+ }
+ 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_MANAGE_TEAM = &Permission{
+ "manage_team",
+ "authentication.permissions.manage_team.name",
+ "authentication.permissions.manage_team.description",
+ }
+ PERMISSION_IMPORT_TEAM = &Permission{
+ "import_team",
+ "authentication.permissions.import_team.name",
+ "authentication.permissions.import_team.description",
+ }
+}
+
+func InitalizeRoles() {
+ InitalizePermissions()
+ BuiltInRoles = make(map[string]*Role)
+
+ ROLE_CHANNEL_USER = &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_MANAGE_PRIVATE_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,
+ },
+ }
+ BuiltInRoles[ROLE_CHANNEL_USER.Id] = ROLE_CHANNEL_USER
+ ROLE_CHANNEL_ADMIN = &Role{
+ "channel_admin",
+ "authentication.roles.channel_admin.name",
+ "authentication.roles.channel_admin.description",
+ []string{},
+ }
+ BuiltInRoles[ROLE_CHANNEL_ADMIN.Id] = ROLE_CHANNEL_ADMIN
+ ROLE_CHANNEL_GUEST = &Role{
+ "guest",
+ "authentication.roles.global_guest.name",
+ "authentication.roles.global_guest.description",
+ []string{},
+ }
+ BuiltInRoles[ROLE_CHANNEL_GUEST.Id] = ROLE_CHANNEL_GUEST
+
+ ROLE_TEAM_USER = &Role{
+ "team_user",
+ "authentication.roles.team_user.name",
+ "authentication.roles.team_user.description",
+ []string{
+ PERMISSION_LIST_TEAM_CHANNELS.Id,
+ PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
+ },
+ }
+ BuiltInRoles[ROLE_TEAM_USER.Id] = ROLE_TEAM_USER
+ ROLE_TEAM_ADMIN = &Role{
+ "team_admin",
+ "authentication.roles.team_admin.name",
+ "authentication.roles.team_admin.description",
+ []string{
+ PERMISSION_EDIT_OTHERS_POSTS.Id,
+ PERMISSION_ADD_USER_TO_TEAM.Id,
+ PERMISSION_REMOVE_USER_FROM_TEAM.Id,
+ PERMISSION_MANAGE_TEAM.Id,
+ PERMISSION_IMPORT_TEAM.Id,
+ PERMISSION_MANAGE_ROLES.Id,
+ PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
+ PERMISSION_MANAGE_SLASH_COMMANDS.Id,
+ PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
+ PERMISSION_MANAGE_WEBHOOKS.Id,
+ },
+ }
+ BuiltInRoles[ROLE_TEAM_ADMIN.Id] = ROLE_TEAM_ADMIN
+
+ ROLE_SYSTEM_USER = &Role{
+ "system_user",
+ "authentication.roles.global_user.name",
+ "authentication.roles.global_user.description",
+ []string{
+ PERMISSION_CREATE_DIRECT_CHANNEL.Id,
+ PERMISSION_PERMANENT_DELETE_USER.Id,
+ },
+ }
+ BuiltInRoles[ROLE_SYSTEM_USER.Id] = ROLE_SYSTEM_USER
+ ROLE_SYSTEM_ADMIN = &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_PUBLIC_CHANNEL_PROPERTIES.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,
+ },
+ ROLE_TEAM_USER.Permissions...,
+ ),
+ ROLE_CHANNEL_USER.Permissions...,
+ ),
+ ROLE_TEAM_ADMIN.Permissions...,
+ ),
+ ROLE_CHANNEL_ADMIN.Permissions...,
+ ),
+ }
+ BuiltInRoles[ROLE_SYSTEM_ADMIN.Id] = ROLE_SYSTEM_ADMIN
+
+}
+
+func RoleIdsToString(roles []string) string {
+ output := ""
+ for _, role := range roles {
+ output += role + ", "
+ }
+
+ if output == "" {
+ return "[<NO ROLES>]"
+ }
+
+ return output[:len(output)-1]
+}
+
+func init() {
+ InitalizeRoles()
+}
diff --git a/model/channel_member.go b/model/channel_member.go
index 66e20da64..705c6bfbd 100644
--- a/model/channel_member.go
+++ b/model/channel_member.go
@@ -10,7 +10,6 @@ import (
)
const (
- CHANNEL_ROLE_ADMIN = "admin"
CHANNEL_NOTIFY_DEFAULT = "default"
CHANNEL_NOTIFY_ALL = "all"
CHANNEL_NOTIFY_MENTION = "mention"
@@ -60,12 +59,6 @@ func (o *ChannelMember) IsValid() *AppError {
return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.user_id.app_error", nil, "")
}
- for _, role := range strings.Split(o.Roles, " ") {
- if !(role == "" || role == CHANNEL_ROLE_ADMIN) {
- return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.role.app_error", nil, "role="+role)
- }
- }
-
notifyLevel := o.NotifyProps["desktop"]
if len(notifyLevel) > 20 || !IsChannelNotifyLevelValid(notifyLevel) {
return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.notify_level.app_error",
@@ -89,6 +82,10 @@ func (o *ChannelMember) PreUpdate() {
o.LastUpdateAt = GetMillis()
}
+func (o *ChannelMember) GetRoles() []string {
+ return strings.Fields(o.Roles)
+}
+
func IsChannelNotifyLevelValid(notifyLevel string) bool {
return notifyLevel == CHANNEL_NOTIFY_DEFAULT ||
notifyLevel == CHANNEL_NOTIFY_ALL ||
diff --git a/model/channel_member_test.go b/model/channel_member_test.go
index cff48ae27..e43560cee 100644
--- a/model/channel_member_test.go
+++ b/model/channel_member_test.go
@@ -30,14 +30,15 @@ func TestChannelMemberIsValid(t *testing.T) {
t.Fatal("should be invalid")
}
- o.Roles = "missing"
+ o.NotifyProps = GetDefaultChannelNotifyProps()
+ o.UserId = NewId()
+ /*o.Roles = "missing"
o.NotifyProps = GetDefaultChannelNotifyProps()
o.UserId = NewId()
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
- }
+ }*/
- o.Roles = CHANNEL_ROLE_ADMIN
o.NotifyProps["desktop"] = "junk"
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
diff --git a/model/session.go b/model/session.go
index e8b04fbe2..c3171ed7c 100644
--- a/model/session.go
+++ b/model/session.go
@@ -115,6 +115,10 @@ func (me *Session) IsMobileApp() bool {
(strings.HasPrefix(me.DeviceId, PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(me.DeviceId, PUSH_NOTIFY_ANDROID+":"))
}
+func (me *Session) GetUserRoles() []string {
+ return strings.Fields(me.Roles)
+}
+
func SessionsToJson(o []*Session) string {
if b, err := json.Marshal(o); err != nil {
return "[]"
diff --git a/model/team_member.go b/model/team_member.go
index 7d932dec4..f03b064ec 100644
--- a/model/team_member.go
+++ b/model/team_member.go
@@ -9,10 +9,6 @@ import (
"strings"
)
-const (
- ROLE_TEAM_ADMIN = "admin"
-)
-
type TeamMember struct {
TeamId string `json:"team_id"`
UserId string `json:"user_id"`
@@ -59,31 +55,6 @@ func TeamMembersFromJson(data io.Reader) []*TeamMember {
}
}
-func IsValidTeamRoles(teamRoles string) bool {
-
- roles := strings.Split(teamRoles, " ")
-
- for _, r := range roles {
- if !isValidTeamRole(r) {
- return false
- }
- }
-
- return true
-}
-
-func isValidTeamRole(role string) bool {
- if role == "" {
- return true
- }
-
- if role == ROLE_TEAM_ADMIN {
- return true
- }
-
- return false
-}
-
func IsInTeamRole(teamRoles string, inRole string) bool {
roles := strings.Split(teamRoles, " ")
@@ -98,7 +69,7 @@ func IsInTeamRole(teamRoles string, inRole string) bool {
}
func (o *TeamMember) IsTeamAdmin() bool {
- return IsInTeamRole(o.Roles, ROLE_TEAM_ADMIN)
+ return true
}
func (o *TeamMember) IsValid() *AppError {
@@ -111,11 +82,18 @@ func (o *TeamMember) IsValid() *AppError {
return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.user_id.app_error", nil, "")
}
- for _, role := range strings.Split(o.Roles, " ") {
- if !(role == "" || role == ROLE_TEAM_ADMIN) {
+ /*for _, role := range strings.Split(o.Roles, " ") {
+ if !(role == "" || role == ROLE_TEAM_ADMIN.Id) {
return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.role.app_error", nil, "role="+role)
}
- }
+ }*/
return nil
}
+
+func (o *TeamMember) PreUpdate() {
+}
+
+func (o *TeamMember) GetRoles() []string {
+ return strings.Fields(o.Roles)
+}
diff --git a/model/team_member_test.go b/model/team_member_test.go
index d5b2e3b79..eac07c646 100644
--- a/model/team_member_test.go
+++ b/model/team_member_test.go
@@ -30,7 +30,7 @@ func TestTeamMemberIsValid(t *testing.T) {
t.Fatal("should be invalid")
}
- o.UserId = NewId()
+ /*o.UserId = NewId()
o.Roles = "blahblah"
if err := o.IsValid(); err == nil {
t.Fatal("should be invalid")
@@ -39,5 +39,5 @@ func TestTeamMemberIsValid(t *testing.T) {
o.Roles = ""
if err := o.IsValid(); err != nil {
t.Fatal(err)
- }
+ }*/
}
diff --git a/model/user.go b/model/user.go
index 680bc48c9..b7ac85baa 100644
--- a/model/user.go
+++ b/model/user.go
@@ -15,7 +15,6 @@ import (
)
const (
- ROLE_SYSTEM_ADMIN = "system_admin"
USER_NOTIFY_ALL = "all"
USER_NOTIFY_MENTION = "mention"
USER_NOTIFY_NONE = "none"
@@ -319,9 +318,17 @@ func (u *User) GetDisplayNameForPreference(nameFormat string) string {
return displayName
}
+func (u *User) GetRoles() []string {
+ return strings.Fields(u.Roles)
+}
+
+func (u *User) GetRawRoles() string {
+ return u.Roles
+}
+
func IsValidUserRoles(userRoles string) bool {
- roles := strings.Split(userRoles, " ")
+ roles := strings.Fields(userRoles)
for _, r := range roles {
if !isValidRole(r) {
@@ -332,16 +339,9 @@ func IsValidUserRoles(userRoles string) bool {
return true
}
-func isValidRole(role string) bool {
- if role == "" {
- return true
- }
-
- if role == ROLE_SYSTEM_ADMIN {
- return true
- }
-
- return false
+func isValidRole(roleId string) bool {
+ _, ok := BuiltInRoles[roleId]
+ return ok
}
// Make sure you acually want to use this function. In context.go there are functions to check permissions
diff --git a/model/user_test.go b/model/user_test.go
index 16ac2583b..2f6524c05 100644
--- a/model/user_test.go
+++ b/model/user_test.go
@@ -225,6 +225,10 @@ func TestRoles(t *testing.T) {
t.Fatal()
}
+ if !IsValidUserRoles("system_user system_admin") {
+ t.Fatal()
+ }
+
if IsInRole("system_admin junk", "admin") {
t.Fatal()
}
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index 0544ec76c..b9db80588 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -395,6 +395,8 @@ func (s SqlTeamStore) UpdateMember(member *model.TeamMember) StoreChannel {
go func() {
result := StoreResult{}
+ member.PreUpdate()
+
if result.Err = member.IsValid(); result.Err != nil {
storeChannel <- result
close(storeChannel)
diff --git a/store/sql_upgrade.go b/store/sql_upgrade.go
index 0e25d76be..445f3f349 100644
--- a/store/sql_upgrade.go
+++ b/store/sql_upgrade.go
@@ -15,6 +15,7 @@ import (
)
const (
+ VERSION_3_5_0 = "3.5.0"
VERSION_3_4_0 = "3.4.0"
VERSION_3_3_0 = "3.3.0"
VERSION_3_2_0 = "3.2.0"
@@ -35,6 +36,7 @@ func UpgradeDatabase(sqlStore *SqlStore) {
UpgradeDatabaseToVersion32(sqlStore)
UpgradeDatabaseToVersion33(sqlStore)
UpgradeDatabaseToVersion34(sqlStore)
+ UpgradeDatabaseToVersion35(sqlStore)
// If the SchemaVersion is empty this this is the first time it has ran
// so lets set it to the current version.
@@ -187,3 +189,17 @@ func UpgradeDatabaseToVersion34(sqlStore *SqlStore) {
saveSchemaVersion(sqlStore, VERSION_3_4_0)
}
}
+
+func UpgradeDatabaseToVersion35(sqlStore *SqlStore) {
+ //if shouldPerformUpgrade(sqlStore, VERSION_3_4_0, VERSION_3_5_0) {
+
+ sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user' WHERE Roles = ''")
+ sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user system_admin' WHERE Roles = 'system_admin'")
+ sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user' WHERE Roles = ''")
+ sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user team_admin' WHERE Roles = 'admin'")
+ sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user' WHERE Roles = ''")
+ sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user channel_admin' WHERE Roles = 'admin'")
+
+ //saveSchemaVersion(sqlStore, VERSION_3_5_0)
+ //}
+}
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index fff78c8f2..574385cd0 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -653,7 +653,7 @@ func (us SqlUserStore) GetSystemAdminProfiles() StoreChannel {
var users []*model.User
- if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users WHERE Roles = :Roles", map[string]interface{}{"Roles": "system_admin"}); err != nil {
+ if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users WHERE Roles LIKE :Roles", map[string]interface{}{"Roles": "%system_admin%"}); err != nil {
result.Err = model.NewLocAppError("SqlUserStore.GetSystemAdminProfiles", "store.sql_user.get_sysadmin_profiles.app_error", nil, err.Error())
} else {
diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go
index 753c54a7b..076be1a81 100644
--- a/store/sql_user_store_test.go
+++ b/store/sql_user_store_test.go
@@ -342,7 +342,7 @@ func TestUserStoreGetSystemAdminProfiles(t *testing.T) {
u1 := &model.User{}
u1.Email = model.NewId()
- u1.Roles = model.ROLE_SYSTEM_ADMIN
+ u1.Roles = model.ROLE_SYSTEM_USER.Id + " " + model.ROLE_SYSTEM_ADMIN.Id
Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id}))
diff --git a/utils/authorization.go b/utils/authorization.go
new file mode 100644
index 000000000..23a7673fe
--- /dev/null
+++ b/utils/authorization.go
@@ -0,0 +1,81 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package utils
+
+import "github.com/mattermost/platform/model"
+
+func SetDefaultRolesBasedOnConfig() {
+ // Reset the roles to default to make this logic easier
+ model.InitalizeRoles()
+
+ switch *Cfg.TeamSettings.RestrictPublicChannelManagement {
+ case model.PERMISSIONS_ALL:
+ model.ROLE_CHANNEL_USER.Permissions = append(
+ model.ROLE_CHANNEL_USER.Permissions,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
+ )
+ model.ROLE_TEAM_USER.Permissions = append(
+ model.ROLE_TEAM_USER.Permissions,
+ model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
+ )
+ break
+ case model.PERMISSIONS_TEAM_ADMIN:
+ model.ROLE_TEAM_ADMIN.Permissions = append(
+ model.ROLE_TEAM_ADMIN.Permissions,
+ model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
+ model.PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
+ )
+ break
+ }
+
+ switch *Cfg.TeamSettings.RestrictPrivateChannelManagement {
+ case model.PERMISSIONS_ALL:
+ model.ROLE_CHANNEL_USER.Permissions = append(
+ model.ROLE_CHANNEL_USER.Permissions,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
+ )
+ model.ROLE_TEAM_USER.Permissions = append(
+ model.ROLE_TEAM_USER.Permissions,
+ model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
+ )
+ break
+ case model.PERMISSIONS_TEAM_ADMIN:
+ model.ROLE_TEAM_ADMIN.Permissions = append(
+ model.ROLE_TEAM_ADMIN.Permissions,
+ model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
+ model.PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
+ model.PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
+ )
+ break
+ }
+
+ if !*Cfg.ServiceSettings.EnableOnlyAdminIntegrations {
+ model.ROLE_TEAM_USER.Permissions = append(
+ model.ROLE_TEAM_USER.Permissions,
+ model.PERMISSION_MANAGE_WEBHOOKS.Id,
+ model.PERMISSION_MANAGE_SLASH_COMMANDS.Id,
+ )
+ model.ROLE_SYSTEM_USER.Permissions = append(
+ model.ROLE_SYSTEM_USER.Permissions,
+ model.PERMISSION_MANAGE_OAUTH.Id,
+ )
+ }
+
+ // If team admins are given permission
+ if *Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_TEAM_ADMIN {
+ model.ROLE_TEAM_ADMIN.Permissions = append(
+ model.ROLE_TEAM_ADMIN.Permissions,
+ model.PERMISSION_INVITE_USER.Id,
+ )
+ // If it's not restricted to system admin or team admin, then give all users permission
+ } else if *Cfg.TeamSettings.RestrictTeamInvite != model.PERMISSIONS_SYSTEM_ADMIN {
+ model.ROLE_SYSTEM_USER.Permissions = append(
+ model.ROLE_SYSTEM_USER.Permissions,
+ model.PERMISSION_INVITE_USER.Id,
+ )
+ }
+}
diff --git a/utils/config.go b/utils/config.go
index 2bfb14255..25dec7ace 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -207,6 +207,12 @@ func LoadConfig(fileName string) {
if samlI := einterfaces.GetSamlInterface(); samlI != nil {
samlI.ConfigureSP()
}
+
+ SetDefaultRolesBasedOnConfig()
+}
+
+func RegenerateClientConfig() {
+ ClientCfg = getClientConfig(Cfg)
}
func getClientConfig(c *model.Config) map[string]string {
diff --git a/web/web_test.go b/web/web_test.go
index 5f74430fa..21819191b 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -83,8 +83,10 @@ func TestGetAccessToken(t *testing.T) {
ApiClient.Must(ApiClient.LoginById(ruser.Id, "passwd1"))
ApiClient.SetTeamId(rteam.Data.(*model.Team).Id)
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
app = ApiClient.Must(ApiClient.RegisterApp(app)).Data.(*model.OAuthApp)
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
redirect := ApiClient.Must(ApiClient.AllowOAuth(model.AUTHCODE_RESPONSE_TYPE, app.Id, app.CallbackUrls[0], "all", "123")).Data.(map[string]string)["redirect"]
rurl, _ := url.Parse(redirect)
@@ -207,7 +209,7 @@ func TestIncomingWebhook(t *testing.T) {
c := &api.Context{}
c.RequestId = model.NewId()
c.IpAddress = "cmd_line"
- api.UpdateUserRoles(c, user, model.ROLE_SYSTEM_ADMIN)
+ api.UpdateUserRoles(c, user, model.ROLE_SYSTEM_ADMIN.Id)
ApiClient.Login(user.Email, "passwd1")
ApiClient.SetTeamId(team.Id)
diff --git a/webapp/actions/team_actions.jsx b/webapp/actions/team_actions.jsx
index ea6be8504..3bf25c193 100644
--- a/webapp/actions/team_actions.jsx
+++ b/webapp/actions/team_actions.jsx
@@ -24,7 +24,7 @@ export function createTeam(team, onSuccess, onError) {
AppDispatcher.handleServerAction({
type: ActionTypes.CREATED_TEAM,
team: rteam,
- member: {team_id: rteam.id, user_id: UserStore.getCurrentId(), roles: 'admin'}
+ member: {team_id: rteam.id, user_id: UserStore.getCurrentId(), roles: 'team_admin team_user'}
});
browserHistory.push('/' + rteam.name + '/channels/town-square');
diff --git a/webapp/components/admin_console/user_item.jsx b/webapp/components/admin_console/user_item.jsx
index 974ef8bc9..78fdb085c 100644
--- a/webapp/components/admin_console/user_item.jsx
+++ b/webapp/components/admin_console/user_item.jsx
@@ -97,12 +97,12 @@ export default class UserItem extends React.Component {
e.preventDefault();
const me = UserStore.getCurrentUser();
if (this.props.user.id === me.id) {
- this.handleDemote(this.props.user, 'admin');
+ this.handleDemote(this.props.user, 'team_user team_admin');
} else {
Client.updateRoles(
this.props.team.id,
this.props.user.id,
- 'admin',
+ 'team_user team_admin',
() => {
this.props.refreshProfiles();
},
@@ -119,7 +119,7 @@ export default class UserItem extends React.Component {
Client.updateRoles(
this.props.team.id,
this.props.user.id,
- 'system_admin',
+ 'system_user system_admin',
() => {
this.props.refreshProfiles();
},
@@ -238,11 +238,11 @@ export default class UserItem extends React.Component {
const me = UserStore.getCurrentUser();
const email = user.email;
- let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
- let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
- let showMakeSystemAdmin = user.roles === '' || user.roles === 'admin';
+ let showMakeMember = Utils.isAdmin(teamMember.roles) || Utils.isSystemAdmin(user.roles);
+ let showMakeAdmin = !Utils.isAdmin(teamMember.roles) && !Utils.isSystemAdmin(user.roles);
+ let showMakeSystemAdmin = !Utils.isSystemAdmin(user.roles);
let showMakeActive = false;
- let showMakeNotActive = user.roles !== 'system_admin';
+ let showMakeNotActive = !Utils.isSystemAdmin(user.roles);
const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true';
const showMfaReset = mfaEnabled && user.mfa_active;
diff --git a/webapp/components/team_members_dropdown.jsx b/webapp/components/team_members_dropdown.jsx
index 527161103..6b9390ade 100644
--- a/webapp/components/team_members_dropdown.jsx
+++ b/webapp/components/team_members_dropdown.jsx
@@ -37,12 +37,12 @@ export default class TeamMembersDropdown extends React.Component {
handleMakeMember() {
const me = UserStore.getCurrentUser();
if (this.props.user.id === me.id) {
- this.handleDemote(this.props.user, '');
+ this.handleDemote(this.props.user, 'team_user');
} else {
Client.updateRoles(
this.props.teamMember.team_id,
this.props.user.id,
- '',
+ 'team_user',
() => {
AsyncClient.getTeamMembers(TeamStore.getCurrentId());
AsyncClient.getProfiles();
@@ -93,12 +93,12 @@ export default class TeamMembersDropdown extends React.Component {
handleMakeAdmin() {
const me = UserStore.getCurrentUser();
if (this.props.user.id === me.id) {
- this.handleDemote(this.props.user, 'admin');
+ this.handleDemote(this.props.user, 'team_user team_admin');
} else {
Client.updateRoles(
this.props.teamMember.team_id,
this.props.user.id,
- 'admin',
+ 'team_user team_admin',
() => {
AsyncClient.getTeamMembers(TeamStore.getCurrentId());
AsyncClient.getProfiles();
@@ -186,10 +186,10 @@ export default class TeamMembersDropdown extends React.Component {
}
const me = UserStore.getCurrentUser();
- let showMakeMember = teamMember.roles === 'admin' && user.roles !== 'system_admin';
- let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
+ let showMakeMember = Utils.isAdmin(teamMember.roles) && !Utils.isSystemAdmin(user.roles);
+ let showMakeAdmin = !Utils.isAdmin(teamMember.roles) && !Utils.isSystemAdmin(user.roles);
let showMakeActive = false;
- let showMakeNotActive = user.roles !== 'system_admin';
+ let showMakeNotActive = Utils.isSystemAdmin(user.roles);
if (user.delete_at > 0) {
currentRoles = (
diff --git a/webapp/tests/client_admin.test.jsx b/webapp/tests/client_admin.test.jsx
index a6a6e1a85..2ed08dc62 100644
--- a/webapp/tests/client_admin.test.jsx
+++ b/webapp/tests/client_admin.test.jsx
@@ -15,7 +15,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -30,7 +30,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -45,7 +45,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -69,7 +69,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -84,7 +84,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -99,7 +99,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -114,7 +114,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -131,7 +131,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -148,7 +148,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -167,7 +167,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
@@ -186,7 +186,7 @@ describe('Client.Admin', function() {
done(new Error('should need system admin permissions'));
},
function(err) {
- assert.equal(err.id, 'api.context.system_permissions.app_error');
+ assert.equal(err.id, 'api.context.permissions.app_error');
done();
}
);
diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx
index dda1d0986..4dc9aab86 100644
--- a/webapp/utils/utils.jsx
+++ b/webapp/utils/utils.jsx
@@ -56,7 +56,7 @@ export function isInRole(roles, inRole) {
}
export function isAdmin(roles) {
- if (isInRole(roles, 'admin')) {
+ if (isInRole(roles, 'team_admin')) {
return true;
}