From 1e7985a87a72bea9a308cf1506dacc828c6e2e1c Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 13 Sep 2016 12:42:48 -0400 Subject: Modifying permissions system. (#3897) --- model/authorization.go | 371 +++++++++++++++++++++++++++++++++++++++++++ model/channel_member.go | 11 +- model/channel_member_test.go | 7 +- model/session.go | 4 + model/team_member.go | 44 ++--- model/team_member_test.go | 4 +- model/user.go | 24 +-- model/user_test.go | 4 + 8 files changed, 412 insertions(+), 57 deletions(-) create mode 100644 model/authorization.go (limited to 'model') 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 "[]" + } + + 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() } -- cgit v1.2.3-1-g7c22