Adding list/join public/private teams permissions (#10309)

* Adding list/join public/private teams permissions

* Add permission migration and allow to migrate based on role name

* Adding JoinTeam new endpoint

* Addressing PR review comments

* Keep the previous API consistent
Этот коммит содержится в:
Jesús Espino
2019-03-19 11:36:29 +01:00
коммит произвёл GitHub
родитель 030ba52b08
Коммит 5a9d95d9c7
13 изменённых файлов: 802 добавлений и 217 удалений

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

@@ -121,6 +121,8 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_DELETE_OTHERS_POSTS.Id,
},
"system_user": []string{
model.PERMISSION_LIST_PUBLIC_TEAMS.Id,
model.PERMISSION_JOIN_PUBLIC_TEAMS.Id,
model.PERMISSION_CREATE_DIRECT_CHANNEL.Id,
model.PERMISSION_CREATE_GROUP_CHANNEL.Id,
model.PERMISSION_PERMANENT_DELETE_USER.Id,
@@ -173,6 +175,8 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_MANAGE_BOTS.Id,
model.PERMISSION_MANAGE_OTHERS_BOTS.Id,
model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id,
model.PERMISSION_LIST_PRIVATE_TEAMS.Id,
model.PERMISSION_JOIN_PRIVATE_TEAMS.Id,
model.PERMISSION_LIST_TEAM_CHANNELS.Id,
model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
@@ -298,6 +302,8 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_DELETE_OTHERS_POSTS.Id,
},
"system_user": []string{
model.PERMISSION_LIST_PUBLIC_TEAMS.Id,
model.PERMISSION_JOIN_PUBLIC_TEAMS.Id,
model.PERMISSION_CREATE_DIRECT_CHANNEL.Id,
model.PERMISSION_CREATE_GROUP_CHANNEL.Id,
model.PERMISSION_PERMANENT_DELETE_USER.Id,
@@ -350,6 +356,8 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PERMISSION_MANAGE_BOTS.Id,
model.PERMISSION_MANAGE_OTHERS_BOTS.Id,
model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id,
model.PERMISSION_LIST_PRIVATE_TEAMS.Id,
model.PERMISSION_JOIN_PRIVATE_TEAMS.Id,
model.PERMISSION_LIST_TEAM_CHANNELS.Id,
model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
@@ -491,6 +499,8 @@ func TestDoEmojisPermissionsMigration(t *testing.T) {
model.PERMISSION_MANAGE_BOTS.Id,
model.PERMISSION_MANAGE_OTHERS_BOTS.Id,
model.PERMISSION_REMOVE_OTHERS_REACTIONS.Id,
model.PERMISSION_LIST_PRIVATE_TEAMS.Id,
model.PERMISSION_JOIN_PRIVATE_TEAMS.Id,
model.PERMISSION_LIST_TEAM_CHANNELS.Id,
model.PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
model.PERMISSION_READ_PUBLIC_CHANNEL.Id,
@@ -568,6 +578,8 @@ func TestDoEmojisPermissionsMigration(t *testing.T) {
role3, err3 := th.App.GetRoleByName(model.SYSTEM_USER_ROLE_ID)
assert.Nil(t, err3)
expected3 := []string{
model.PERMISSION_LIST_PUBLIC_TEAMS.Id,
model.PERMISSION_JOIN_PUBLIC_TEAMS.Id,
model.PERMISSION_CREATE_DIRECT_CHANNEL.Id,
model.PERMISSION_CREATE_GROUP_CHANNEL.Id,
model.PERMISSION_PERMANENT_DELETE_USER.Id,

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

@@ -3,19 +3,23 @@
package app
import "github.com/mattermost/mattermost-server/model"
import (
"github.com/mattermost/mattermost-server/model"
)
type permissionTransformation struct {
On func(map[string]bool) bool
On func(string, map[string]bool) bool
Add []string
Remove []string
}
type permissionsMap []permissionTransformation
const (
MIGRATION_KEY_EMOJI_PERMISSIONS_SPLIT = "emoji_permissions_split"
MIGRATION_KEY_WEBHOOK_PERMISSIONS_SPLIT = "webhook_permissions_split"
MIGRATION_KEY_EMOJI_PERMISSIONS_SPLIT = "emoji_permissions_split"
MIGRATION_KEY_WEBHOOK_PERMISSIONS_SPLIT = "webhook_permissions_split"
MIGRATION_KEY_LIST_JOIN_PUBLIC_PRIVATE_TEAMS = "list_join_public_private_teams"
PERMISSION_MANAGE_SYSTEM = "manage_system"
PERMISSION_MANAGE_EMOJIS = "manage_emojis"
PERMISSION_MANAGE_OTHERS_EMOJIS = "manage_others_emojis"
PERMISSION_CREATE_EMOJIS = "create_emojis"
@@ -27,26 +31,36 @@ const (
PERMISSION_MANAGE_OTHERS_INCOMING_WEBHOOKS = "manage_others_incoming_webhooks"
PERMISSION_MANAGE_OUTGOING_WEBHOOKS = "manage_outgoing_webhooks"
PERMISSION_MANAGE_OTHERS_OUTGOING_WEBHOOKS = "manage_others_outgoing_webhooks"
PERMISSION_LIST_PUBLIC_TEAMS = "list_public_teams"
PERMISSION_LIST_PRIVATE_TEAMS = "list_private_teams"
PERMISSION_JOIN_PUBLIC_TEAMS = "join_public_teams"
PERMISSION_JOIN_PRIVATE_TEAMS = "join_private_teams"
)
func permissionExists(permission string) func(map[string]bool) bool {
return func(permissions map[string]bool) bool {
func isRole(role string) func(string, map[string]bool) bool {
return func(roleName string, permissions map[string]bool) bool {
return roleName == role
}
}
func permissionExists(permission string) func(string, map[string]bool) bool {
return func(roleName string, permissions map[string]bool) bool {
val, ok := permissions[permission]
return ok && val
}
}
func permissionNotExists(permission string) func(map[string]bool) bool {
return func(permissions map[string]bool) bool {
func permissionNotExists(permission string) func(string, map[string]bool) bool {
return func(roleName string, permissions map[string]bool) bool {
val, ok := permissions[permission]
return !(ok && val)
}
}
func permissionOr(funcs ...func(map[string]bool) bool) func(map[string]bool) bool {
return func(permissions map[string]bool) bool {
func permissionOr(funcs ...func(string, map[string]bool) bool) func(string, map[string]bool) bool {
return func(roleName string, permissions map[string]bool) bool {
for _, f := range funcs {
if f(permissions) {
if f(roleName, permissions) {
return true
}
}
@@ -54,10 +68,10 @@ func permissionOr(funcs ...func(map[string]bool) bool) func(map[string]bool) boo
}
}
func permissionAnd(funcs ...func(map[string]bool) bool) func(map[string]bool) bool {
return func(permissions map[string]bool) bool {
func permissionAnd(funcs ...func(string, map[string]bool) bool) func(string, map[string]bool) bool {
return func(roleName string, permissions map[string]bool) bool {
for _, f := range funcs {
if !f(permissions) {
if !f(roleName, permissions) {
return false
}
}
@@ -65,7 +79,7 @@ func permissionAnd(funcs ...func(map[string]bool) bool) func(map[string]bool) bo
}
}
func applyPermissionsMap(permissions []string, migrationMap permissionsMap) []string {
func applyPermissionsMap(roleName string, permissions []string, migrationMap permissionsMap) []string {
finalMap := make(map[string]bool)
var result []string
for _, permission := range permissions {
@@ -73,7 +87,7 @@ func applyPermissionsMap(permissions []string, migrationMap permissionsMap) []st
}
for _, transformation := range migrationMap {
if transformation.On(finalMap) {
if transformation.On(roleName, finalMap) {
for _, add := range transformation.Add {
finalMap[add] = true
}
@@ -102,7 +116,7 @@ func (a *App) doPermissionsMigration(key string, migrationMap permissionsMap) *m
}
for _, role := range roles {
role.Permissions = applyPermissionsMap(role.Permissions, migrationMap)
role.Permissions = applyPermissionsMap(role.Name, role.Permissions, migrationMap)
if result := <-a.Srv.Store.Role().Save(role); result.Err != nil {
return result.Err
}
@@ -144,6 +158,21 @@ func getWebhooksPermissionsSplitMigration() permissionsMap {
}
}
func getListJoinPublicPrivateTeamsPermissionsMigration() permissionsMap {
return permissionsMap{
permissionTransformation{
On: isRole(model.SYSTEM_ADMIN_ROLE_ID),
Add: []string{PERMISSION_LIST_PRIVATE_TEAMS, PERMISSION_JOIN_PRIVATE_TEAMS},
Remove: []string{},
},
permissionTransformation{
On: isRole(model.SYSTEM_USER_ROLE_ID),
Add: []string{PERMISSION_LIST_PUBLIC_TEAMS, PERMISSION_JOIN_PUBLIC_TEAMS},
Remove: []string{},
},
}
}
// DoPermissionsMigrations execute all the permissions migrations need by the current version.
func (a *App) DoPermissionsMigrations() *model.AppError {
PermissionsMigrations := []struct {
@@ -152,6 +181,7 @@ func (a *App) DoPermissionsMigrations() *model.AppError {
}{
{Key: MIGRATION_KEY_EMOJI_PERMISSIONS_SPLIT, Migration: getEmojisPermissionsSplitMigration},
{Key: MIGRATION_KEY_WEBHOOK_PERMISSIONS_SPLIT, Migration: getWebhooksPermissionsSplitMigration},
{Key: MIGRATION_KEY_LIST_JOIN_PUBLIC_PRIVATE_TEAMS, Migration: getListJoinPublicPrivateTeamsPermissionsMigration},
}
for _, migration := range PermissionsMigrations {

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

@@ -77,11 +77,29 @@ func TestApplyPermissionsMap(t *testing.T) {
}},
[]string{"test1", "test2", "test3"},
},
{
"When the role matches",
[]string{"test1", "test2", "test3"},
permissionsMap{permissionTransformation{
On: isRole("system_admin"),
Add: []string{"test4"},
}},
[]string{"test1", "test2", "test3", "test4"},
},
{
"When the role doesn't match",
[]string{"test1", "test2", "test3"},
permissionsMap{permissionTransformation{
On: isRole("system_user"),
Add: []string{"test4"},
}},
[]string{"test1", "test2", "test3"},
},
}
for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) {
result := applyPermissionsMap(tc.Permissions, tc.TranslationMap)
result := applyPermissionsMap("system_admin", tc.Permissions, tc.TranslationMap)
sort.Strings(result)
assert.Equal(t, tc.ExpectedResult, result)
})

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

@@ -562,7 +562,23 @@ func (a *App) GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppE
return result.Data.([]*model.Team), nil
}
func (a *App) GetAllOpenTeams() ([]*model.Team, *model.AppError) {
func (a *App) GetAllPrivateTeams() ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().GetAllPrivateTeamListing()
if result.Err != nil {
return nil, result.Err
}
return result.Data.([]*model.Team), nil
}
func (a *App) GetAllPrivateTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().GetAllPrivateTeamPageListing(offset, limit)
if result.Err != nil {
return nil, result.Err
}
return result.Data.([]*model.Team), nil
}
func (a *App) GetAllPublicTeams() ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().GetAllTeamListing()
if result.Err != nil {
return nil, result.Err
@@ -570,6 +586,14 @@ func (a *App) GetAllOpenTeams() ([]*model.Team, *model.AppError) {
return result.Data.([]*model.Team), nil
}
func (a *App) GetAllPublicTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().GetAllTeamPageListing(offset, limit)
if result.Err != nil {
return nil, result.Err
}
return result.Data.([]*model.Team), nil
}
func (a *App) SearchAllTeams(term string) ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().SearchAll(term)
if result.Err != nil {
@@ -578,7 +602,7 @@ func (a *App) SearchAllTeams(term string) ([]*model.Team, *model.AppError) {
return result.Data.([]*model.Team), nil
}
func (a *App) SearchOpenTeams(term string) ([]*model.Team, *model.AppError) {
func (a *App) SearchPublicTeams(term string) ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().SearchOpen(term)
if result.Err != nil {
return nil, result.Err
@@ -586,8 +610,8 @@ func (a *App) SearchOpenTeams(term string) ([]*model.Team, *model.AppError) {
return result.Data.([]*model.Team), nil
}
func (a *App) GetAllOpenTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().GetAllTeamPageListing(offset, limit)
func (a *App) SearchPrivateTeams(term string) ([]*model.Team, *model.AppError) {
result := <-a.Srv.Store.Team().SearchPrivate(term)
if result.Err != nil {
return nil, result.Err
}